Skip to content

Commit 9b4486a

Browse files
authored
Split the docker image to improve caching (#10924)
* Split the docker image to improve caching
1 parent 2c65f43 commit 9b4486a

File tree

7 files changed

+331
-245
lines changed

7 files changed

+331
-245
lines changed

.github/workflows/oci.yaml

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,22 @@ concurrency:
1515
jobs:
1616
build-publish-dev-bazel:
1717
runs-on: ubuntu-latest
18+
services:
19+
registry:
20+
image: registry
21+
ports:
22+
- 5001:5000
1823
steps:
1924
- name: Checkout
2025
uses: actions/checkout@v4
2126

27+
- name: 'Login to GitHub Container Registry'
28+
uses: docker/login-action@v1
29+
with:
30+
registry: ghcr.io
31+
username: ${{ github.actor }}
32+
password: ${{ secrets.GHCR_TOKEN }}
33+
2234
- name: Set up QEMU
2335
uses: docker/setup-qemu-action@v3
2436

@@ -46,15 +58,32 @@ jobs:
4658
build:buildbuddy --build_metadata=VISIBILITY=PRIVATE
4759
build:buildbuddy --color=yes
4860
49-
build --experimental_ui_max_stdouterr_bytes=4194304
5061
build --action_env EXTRA_BUILDX_OPTS="--cache-from=type=gha --cache-to=type=gha"
62+
build --action_env TEMP_REGISTRY="ghcr.io/rabbitmq/"
5163
EOF
5264
65+
- name: Build package-generic-unix
66+
run: |
67+
bazelisk build :package-generic-unix \
68+
--config=buildbuddy
69+
70+
- name: Build amd64 Base
71+
run: |
72+
bazelisk build //packaging/base-image:docker-build-amd64 \
73+
--config=buildbuddy \
74+
--experimental_ui_max_stdouterr_bytes=4194304
75+
5376
- name: Build amd64
5477
run: |
5578
bazelisk build //packaging/docker-image:rabbitmq-amd64 \
5679
--config=buildbuddy
5780
81+
- name: Build arm64 Base
82+
run: |
83+
bazelisk build //packaging/base-image:docker-build-arm64 \
84+
--config=buildbuddy \
85+
--experimental_ui_max_stdouterr_bytes=4194304
86+
5887
- name: Build arm64
5988
run: |
6089
bazelisk build //packaging/docker-image:rabbitmq-arm64 \

packaging/base-image/.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
BUILD.bazel

packaging/base-image/BUILD.bazel

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
_ARCHS = [
2+
"amd64",
3+
"arm64",
4+
]
5+
6+
_TAGS = [
7+
"docker",
8+
"manual",
9+
"no-sandbox",
10+
"no-remote-exec", # buildbuddy runners do not have the emulator available
11+
]
12+
13+
[
14+
genrule(
15+
name = "docker-build-%s" % arch,
16+
srcs = [
17+
"Dockerfile",
18+
],
19+
outs = [
20+
"image-%s.tar" % arch,
21+
],
22+
cmd = """set -euo pipefail
23+
24+
CONTEXT="$$(mktemp -d)"
25+
26+
cp $(location Dockerfile) "$$CONTEXT"
27+
28+
docker buildx \\
29+
build \\
30+
"$$CONTEXT" \\
31+
--platform linux/{arch} \\
32+
--output type=tar,dest=$(location image-{arch}.tar) $${{EXTRA_BUILDX_OPTS:-}}
33+
""".format(
34+
arch = arch,
35+
),
36+
tags = _TAGS,
37+
visibility = ["//packaging:__subpackages__"],
38+
)
39+
for arch in _ARCHS
40+
]

packaging/base-image/Dockerfile

Lines changed: 233 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,234 @@
1-
# The official Canonical Ubuntu Bionic image is ideal from a security perspective,
1+
#
2+
# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh"
3+
#
4+
# PLEASE DO NOT EDIT IT DIRECTLY.
5+
#
6+
7+
# The official Canonical Ubuntu Focal image is ideal from a security perspective,
28
# especially for the enterprises that we, the RabbitMQ team, have to deal with
3-
FROM ubuntu:20.04
4-
5-
RUN set -eux; \
6-
apt-get update; \
7-
apt-get install -y lsb-release ubuntu-dbgsym-keyring; \
8-
echo "deb http://ddebs.ubuntu.com $(lsb_release -cs) main restricted universe multiverse" > /etc/apt/sources.list.d/ddebs.list; \
9-
echo "deb http://ddebs.ubuntu.com $(lsb_release -cs)-updates main restricted universe multiverse" >> /etc/apt/sources.list.d/ddebs.list; \
10-
echo "deb http://ddebs.ubuntu.com $(lsb_release -cs)-proposed main restricted universe multiverse" >> /etc/apt/sources.list.d/ddebs.list; \
11-
apt-get update; \
12-
apt-get install -y --no-install-recommends \
13-
libc6-dbg \
14-
libtinfo6-dbgsym
9+
10+
FROM ubuntu:22.04 as build-base
11+
12+
ARG BUILDKIT_SBOM_SCAN_STAGE=true
13+
14+
RUN set -eux; \
15+
apt-get update; \
16+
apt-get install -y --no-install-recommends \
17+
build-essential \
18+
ca-certificates \
19+
gnupg \
20+
libncurses5-dev \
21+
wget
22+
23+
FROM build-base as openssl-builder
24+
25+
ARG BUILDKIT_SBOM_SCAN_STAGE=true
26+
27+
# Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally
28+
ARG PGP_KEYSERVER=keyserver.ubuntu.com
29+
# If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors,
30+
# run the build with a different PGP_KEYSERVER, e.g. docker build --tag rabbitmq:3.13 --build-arg PGP_KEYSERVER=pgpkeys.eu 3.13/ubuntu
31+
# For context, see https://github.com/docker-library/official-images/issues/4252
32+
33+
ENV OPENSSL_VERSION 3.1.5
34+
ENV OPENSSL_SOURCE_SHA256="6ae015467dabf0469b139ada93319327be24b98251ffaeceda0221848dc09262"
35+
# https://www.openssl.org/community/otc.html
36+
# https://www.openssl.org/source/
37+
ENV OPENSSL_PGP_KEY_IDS="0x8657ABB260F056B1E5190839D9C4D26D0E604491 0xB7C1C14360F353A36862E4D5231C84CDDCC69C45 0xC1F33DD8CE1D4CC613AF14DA9195C48241FBF7DD 0x95A9908DDFA16830BE9FB9003D30A3A9FF1360DC 0x7953AC1FBC3DC8B3B292393ED5E9E43F7DF9EE8C 0xA21FAB74B0088AA361152586B8EF1A6BA9DA2D5C 0xE5E52560DD91C556DDBDA5D02064C53641C25E5D 0xEFC0A467D613CB83C7ED6D30D894E2CE8B3D79F5"
38+
39+
ENV OTP_VERSION 26.2.2
40+
# TODO add PGP checking when the feature will be added to Erlang/OTP's build system
41+
# https://erlang.org/pipermail/erlang-questions/2019-January/097067.html
42+
ENV OTP_SOURCE_SHA256="d537ff4ac5d8c1cb507aedaf7198fc1f155ea8aa65a8d83edb35c2802763cc28"
43+
44+
# install openssl & erlang to a path that isn't auto-checked for libs to prevent accidental use by system packages
45+
ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang
46+
ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl
47+
48+
# Install dependencies required to build Erlang/OTP from source
49+
# https://erlang.org/doc/installation_guide/INSTALL.html
50+
# dpkg-dev: Required to set up host & build type when compiling Erlang/OTP
51+
# gnupg: Required to verify OpenSSL artefacts
52+
# libncurses5-dev: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli
53+
RUN set -eux; \
54+
OPENSSL_SOURCE_URL="https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz"; \
55+
OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \
56+
OPENSSL_CONFIG_DIR="$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \
57+
\
58+
# Required by the crypto & ssl Erlang/OTP applications
59+
wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_SOURCE_URL.asc"; \
60+
wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz" "$OPENSSL_SOURCE_URL"; \
61+
export GNUPGHOME="$(mktemp -d)"; \
62+
for key in $OPENSSL_PGP_KEY_IDS; do \
63+
gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \
64+
done; \
65+
gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \
66+
gpgconf --kill all; \
67+
rm -rf "$GNUPGHOME"; \
68+
echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum --check --strict -; \
69+
mkdir -p "$OPENSSL_PATH"; \
70+
tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \
71+
\
72+
# Configure OpenSSL for compilation
73+
cd "$OPENSSL_PATH"; \
74+
# without specifying "--libdir", Erlang will fail during "crypto:supports()" looking for a "pthread_atfork" function that doesn't exist (but only on arm32v7/armhf??)
75+
# OpenSSL's "config" script uses a lot of "uname"-based target detection...
76+
dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \
77+
# https://deb.debian.org/debian/dists/unstable/main/
78+
case "$dpkgArch" in \
79+
# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L860 (look for "linux-" and "linux64-" keys)
80+
amd64) opensslMachine='linux-x86_64' ;; \
81+
arm64) opensslMachine='linux-aarch64' ;; \
82+
# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L736-L766
83+
# https://wiki.debian.org/ArchitectureSpecificsMemo#Architecture_baselines
84+
# https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html
85+
armhf) opensslMachine='linux-armv4'; opensslExtraConfig='-march=armv7-a+fp' ;; \
86+
i386) opensslMachine='linux-x86' ;; \
87+
ppc64el) opensslMachine='linux-ppc64le' ;; \
88+
riscv64) opensslMachine='linux64-riscv64' ;; \
89+
s390x) opensslMachine='linux64-s390x' ;; \
90+
*) echo >&2 "error: unsupported arch: '$apkArch'"; exit 1 ;; \
91+
esac; \
92+
MACHINE="$opensslMachine" \
93+
RELEASE="4.x.y-z" \
94+
SYSTEM='Linux' \
95+
BUILD='???' \
96+
./Configure \
97+
"$opensslMachine" \
98+
enable-fips \
99+
--prefix="$OPENSSL_INSTALL_PATH_PREFIX" \
100+
--openssldir="$OPENSSL_CONFIG_DIR" \
101+
--libdir="$OPENSSL_INSTALL_PATH_PREFIX/lib" \
102+
# add -rpath to avoid conflicts between our OpenSSL's "libssl.so" and the libssl package by making sure "$INSTALL_PATH_PREFIX/lib" is searched first (but only for Erlang/OpenSSL to avoid issues with other tools using libssl; https://github.com/docker-library/rabbitmq/issues/364)
103+
-Wl,-rpath="$OPENSSL_INSTALL_PATH_PREFIX/lib" \
104+
${opensslExtraConfig:-} \
105+
; \
106+
# Compile, install OpenSSL, verify that the command-line works & development headers are present
107+
make -j "$(getconf _NPROCESSORS_ONLN)"; \
108+
make install_sw install_ssldirs install_fips; \
109+
ldconfig; \
110+
# use Debian's CA certificates
111+
rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \
112+
ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR"
113+
114+
# smoke test
115+
RUN $OPENSSL_INSTALL_PATH_PREFIX/bin/openssl version
116+
117+
FROM openssl-builder as erlang-builder
118+
119+
ARG BUILDKIT_SBOM_SCAN_STAGE=true
120+
121+
RUN set -eux; \
122+
OTP_SOURCE_URL="https://github.com/erlang/otp/releases/download/OTP-$OTP_VERSION/otp_src_$OTP_VERSION.tar.gz"; \
123+
OTP_PATH="/usr/local/src/otp-$OTP_VERSION"; \
124+
\
125+
# Download, verify & extract OTP_SOURCE
126+
mkdir -p "$OTP_PATH"; \
127+
wget --progress dot:giga --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \
128+
echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum --check --strict -; \
129+
tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \
130+
\
131+
# Configure Erlang/OTP for compilation, disable unused features & applications
132+
# https://erlang.org/doc/applications.html
133+
# ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation
134+
cd "$OTP_PATH"; \
135+
export ERL_TOP="$OTP_PATH"; \
136+
CFLAGS="$(dpkg-buildflags --get CFLAGS)"; export CFLAGS; \
137+
# add -rpath to avoid conflicts between our OpenSSL's "libssl.so" and the libssl package by making sure "$OPENSSL_INSTALL_PATH_PREFIX/lib" is searched first (but only for Erlang/OpenSSL to avoid issues with other tools using libssl; https://github.com/docker-library/rabbitmq/issues/364)
138+
export CFLAGS="$CFLAGS -Wl,-rpath=$OPENSSL_INSTALL_PATH_PREFIX/lib"; \
139+
hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \
140+
buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
141+
dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \
142+
# JIT is only supported on amd64 + arm64; https://github.com/erlang/otp/blob/OTP-25.3.2.2/erts/configure#L24306-L24347
143+
jitFlag=; \
144+
case "$dpkgArch" in \
145+
amd64 | arm64) jitFlag='--enable-jit' ;; \
146+
esac; \
147+
./configure \
148+
--prefix="$ERLANG_INSTALL_PATH_PREFIX" \
149+
--host="$hostArch" \
150+
--build="$buildArch" \
151+
--disable-hipe \
152+
--disable-sctp \
153+
--disable-silent-rules \
154+
--enable-builtin-zlib \
155+
--enable-clock-gettime \
156+
--enable-hybrid-heap \
157+
--enable-kernel-poll \
158+
--enable-smp-support \
159+
--enable-threads \
160+
--with-microstate-accounting=extra \
161+
--with-ssl="$OPENSSL_INSTALL_PATH_PREFIX" \
162+
--without-common_test \
163+
--without-debugger \
164+
--without-dialyzer \
165+
--without-diameter \
166+
--without-edoc \
167+
--without-erl_docgen \
168+
--without-et \
169+
--without-eunit \
170+
--without-ftp \
171+
--without-hipe \
172+
--without-jinterface \
173+
--without-megaco \
174+
--without-observer \
175+
--without-odbc \
176+
--without-reltool \
177+
--without-ssh \
178+
--without-tftp \
179+
--without-wx \
180+
$jitFlag \
181+
; \
182+
\
183+
# Compile & install Erlang/OTP
184+
make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \
185+
make install; \
186+
\
187+
# Remove unnecessary files
188+
find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name examples -exec rm -rf '{}' +; \
189+
find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name src -exec rm -rf '{}' +; \
190+
find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name include -exec rm -rf '{}' +
191+
192+
# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly
193+
ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$PATH
194+
RUN find $ERLANG_INSTALL_PATH_PREFIX -type f -name 'crypto.so' -exec ldd {} \; | awk '/libcrypto\.so/ { if (!index($3,ENVIRON["OPENSSL_INSTALL_PATH_PREFIX"])) exit 1 }'
195+
RUN erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().'
196+
197+
FROM ubuntu:22.04
198+
199+
# OPENSSL/ERLANG_INSTALL_PATH_PREFIX are defined in a different stage, so define them again
200+
ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang
201+
ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl
202+
COPY --from=erlang-builder $ERLANG_INSTALL_PATH_PREFIX $ERLANG_INSTALL_PATH_PREFIX
203+
RUN echo '{"spdxVersion":"SPDX-2.3","SPDXID":"SPDXRef-DOCUMENT","name":"erlang-sbom","packages":[{"name":"erlang","versionInfo":"26.2.2","SPDXID":"SPDXRef-Package--erlang","externalRefs":[{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:generic/[email protected]?os_name=ubuntu&os_version=22.04"}],"licenseDeclared":"Apache-2.0"}]}' > $ERLANG_INSTALL_PATH_PREFIX/erlang.spdx.json
204+
205+
COPY --from=openssl-builder $OPENSSL_INSTALL_PATH_PREFIX $OPENSSL_INSTALL_PATH_PREFIX
206+
RUN echo '{"spdxVersion":"SPDX-2.3","SPDXID":"SPDXRef-DOCUMENT","name":"openssl-sbom","packages":[{"name":"openssl","versionInfo":"3.1.5","SPDXID":"SPDXRef-Package--openssl","externalRefs":[{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:generic/[email protected]?os_name=ubuntu&os_version=22.04"}],"licenseDeclared":"Apache-2.0"}]}' > $OPENSSL_INSTALL_PATH_PREFIX/openssl.spdx.json
207+
208+
ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$OPENSSL_INSTALL_PATH_PREFIX/bin:$PATH
209+
210+
ENV RABBITMQ_DATA_DIR /var/lib/rabbitmq
211+
212+
RUN set -eux; \
213+
# Configure OpenSSL to use system certs
214+
ln -vsf /etc/ssl/certs /etc/ssl/private "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \
215+
\
216+
# Check that OpenSSL still works after copying from previous builder
217+
ldconfig; \
218+
sed -i.ORIG -e "/\.include.*fips/ s!.*!.include $OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf!" \
219+
-e '/# fips =/s/.*/fips = fips_sect/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/openssl.cnf"; \
220+
sed -i.ORIG -e '/^activate/s/^/#/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf"; \
221+
[ "$(command -v openssl)" = "$OPENSSL_INSTALL_PATH_PREFIX/bin/openssl" ]; \
222+
openssl version; \
223+
openssl version -d; \
224+
\
225+
# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly
226+
erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().'; \
227+
\
228+
# Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM
229+
groupadd --gid 999 --system rabbitmq; \
230+
useradd --uid 999 --system --home-dir "$RABBITMQ_DATA_DIR" --gid rabbitmq rabbitmq; \
231+
mkdir -p "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \
232+
chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \
233+
chmod 1777 "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \
234+
ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
test_configs
2+
BUILD.bazel
3+
Makefile

0 commit comments

Comments
 (0)