diff --git a/3.10/alpine/Dockerfile b/3.10/alpine/Dockerfile index d283e70d..cc57c4b6 100644 --- a/3.10/alpine/Dockerfile +++ b/3.10/alpine/Dockerfile @@ -5,17 +5,18 @@ # # Alpine Linux is not officially supported by the RabbitMQ team -- use at your own risk! -FROM alpine:3.17 +FROM alpine:3.17 as build-base RUN apk add --no-cache \ -# grab su-exec for easy step-down from root - 'su-exec>=0.2' \ -# bash for docker-entrypoint.sh - bash \ -# "ps" for "rabbitmqctl wait" (https://github.com/docker-library/rabbitmq/issues/162) - procps \ -# Bring in tzdata so users could set the timezones through the environment - tzdata + build-base \ + dpkg-dev \ + dpkg \ + gnupg \ + libc-dev \ + linux-headers \ + ncurses-dev + +FROM build-base as openssl-builder # Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally ARG PGP_KEYSERVER=keyserver.ubuntu.com @@ -40,26 +41,13 @@ ENV OTP_SOURCE_SHA256="5442dea694e7555d479d80bc81f1428020639c258f8e40b2052732d1c # gnupg: Required to verify OpenSSL artefacts # libncurses5-dev: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli RUN set -eux; \ - \ - apk add --no-cache --virtual .build-deps \ - autoconf \ - dpkg-dev dpkg \ - g++ \ - gcc \ - gnupg \ - libc-dev \ - linux-headers \ - make \ - ncurses-dev \ - ; \ +# /usr/local/src doesn't exist in Alpine by default + mkdir -p /usr/local/src; \ \ OPENSSL_SOURCE_URL="https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz"; \ OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ OPENSSL_CONFIG_DIR=/usr/local/etc/ssl; \ \ -# /usr/local/src doesn't exist in Alpine by default - mkdir /usr/local/src; \ - \ # Required by the crypto & ssl Erlang/OTP applications wget --output-document "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_SOURCE_URL.asc"; \ wget --output-document "$OPENSSL_PATH.tar.gz" "$OPENSSL_SOURCE_URL"; \ @@ -89,13 +77,18 @@ RUN set -eux; \ # Compile, install OpenSSL, verify that the command-line works & development headers are present make -j "$(getconf _NPROCESSORS_ONLN)"; \ make install_sw install_ssldirs; \ - cd ..; \ - rm -rf "$OPENSSL_PATH"*; \ # use Alpine's CA certificates rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ - ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR"; \ + ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR" + # smoke test - openssl version; \ +RUN openssl version + +FROM openssl-builder as erlang-builder + +RUN set -eux; \ +# /usr/local/src doesn't exist in Alpine by default + mkdir -p /usr/local/src; \ \ OTP_SOURCE_URL="https://github.com/erlang/otp/releases/download/OTP-$OTP_VERSION/otp_src_$OTP_VERSION.tar.gz"; \ OTP_PATH="/usr/local/src/otp-$OTP_VERSION"; \ @@ -111,7 +104,6 @@ RUN set -eux; \ # ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation cd "$OTP_PATH"; \ export ERL_TOP="$OTP_PATH"; \ - ./otp_build autoconf; \ export CFLAGS='-g -O2'; \ # add -rpath to avoid conflicts between our OpenSSL's "libssl.so" and the libssl package by making sure /usr/local/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) export CFLAGS="$CFLAGS -Wl,-rpath=/usr/local/lib"; \ @@ -160,36 +152,59 @@ RUN set -eux; \ # Compile & install Erlang/OTP make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ make install; \ - cd ..; \ - rm -rf \ - "$OTP_PATH"* \ - /usr/local/lib/erlang/lib/*/examples \ - /usr/local/lib/erlang/lib/*/src \ - ; \ \ +# Remove unnecessary files + find /usr/local/lib/erlang -type d -name examples -exec rm -rf '{}' +; \ + find /usr/local/lib/erlang -type d -name src -exec rm -rf '{}' +; \ + find /usr/local/lib/erlang -type d -name include -exec rm -rf '{}' + + +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly +RUN erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' + +FROM alpine:3.17 + +COPY --from=erlang-builder /usr/local/bin/ /usr/local/bin/ +COPY --from=erlang-builder /usr/local/etc/ssl/ /usr/local/etc/ssl/ +COPY --from=erlang-builder /usr/local/lib/ /usr/local/lib/ + +ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq + +RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private /usr/local/etc/ssl; \ + \ +# Ensure run-time dependencies are installed runDeps="$( \ scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ | tr ',' '\n' \ | sort -u \ - | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ + | awk 'system("test -e /usr/local/lib/" $1) == 0 { next } { print "so:" $1 }' \ )"; \ apk add --no-cache --virtual .otp-run-deps $runDeps; \ - apk del --no-network .build-deps; \ \ -# Check that OpenSSL still works after purging build dependencies +# Check that OpenSSL still works after copying from previous builder openssl version; \ + \ # Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly - erl -noshell -eval 'io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' - -ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq + erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().'; \ + \ # Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM -RUN set -eux; \ addgroup -g 101 -S rabbitmq; \ adduser -u 100 -S -h "$RABBITMQ_DATA_DIR" -G rabbitmq rabbitmq; \ mkdir -p "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ chmod 777 "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ - ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie + ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie; \ + \ + apk add --no-cache \ +# grab su-exec for easy step-down from root + 'su-exec>=0.2' \ +# bash for docker-entrypoint.sh + bash \ +# "ps" for "rabbitmqctl wait" (https://github.com/docker-library/rabbitmq/issues/162) + procps \ +# Bring in tzdata so users could set the timezones through the environment + tzdata # Use the latest stable RabbitMQ release (https://www.rabbitmq.com/download.html) ENV RABBITMQ_VERSION 3.10.13 @@ -202,6 +217,8 @@ ENV PATH=$RABBITMQ_HOME/sbin:$PATH # Install RabbitMQ RUN set -eux; \ +# /usr/local/src doesn't exist in Alpine by default + mkdir -p /usr/local/src; \ \ apk add --no-cache --virtual .build-deps \ gnupg \ @@ -229,7 +246,7 @@ RUN set -eux; \ grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ \ - apk del .build-deps; \ + apk del --no-network .build-deps; \ \ # verify assumption of no stale cookies [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ diff --git a/3.10/ubuntu/Dockerfile b/3.10/ubuntu/Dockerfile index fc919d77..d657d87c 100644 --- a/3.10/ubuntu/Dockerfile +++ b/3.10/ubuntu/Dockerfile @@ -6,19 +6,18 @@ # The official Canonical Ubuntu Focal image is ideal from a security perspective, # especially for the enterprises that we, the RabbitMQ team, have to deal with -FROM ubuntu:20.04 +FROM ubuntu:20.04 as build-base RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends \ -# grab gosu for easy step-down from root - gosu \ -# Bring in tzdata so users could set the timezones through the environment - tzdata \ - ; \ - rm -rf /var/lib/apt/lists/*; \ -# verify that the "gosu" binary works - gosu nobody true + build-essential \ + ca-certificates \ + gnupg \ + libncurses5-dev \ + wget + +FROM build-base as openssl-builder # Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally ARG PGP_KEYSERVER=keyserver.ubuntu.com @@ -43,22 +42,6 @@ ENV OTP_SOURCE_SHA256="5442dea694e7555d479d80bc81f1428020639c258f8e40b2052732d1c # gnupg: Required to verify OpenSSL artefacts # libncurses5-dev: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli RUN set -eux; \ - \ - savedAptMark="$(apt-mark showmanual)"; \ - apt-get update; \ - apt-get install --yes --no-install-recommends \ - autoconf \ - ca-certificates \ - dpkg-dev \ - gcc \ - g++ \ - gnupg \ - libncurses5-dev \ - make \ - wget \ - ; \ - rm -rf /var/lib/apt/lists/*; \ - \ OPENSSL_SOURCE_URL="https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz"; \ OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ OPENSSL_CONFIG_DIR=/usr/local/etc/ssl; \ @@ -95,15 +78,17 @@ RUN set -eux; \ # Compile, install OpenSSL, verify that the command-line works & development headers are present make -j "$(getconf _NPROCESSORS_ONLN)"; \ make install_sw install_ssldirs; \ - cd ..; \ - rm -rf "$OPENSSL_PATH"*; \ ldconfig; \ # use Debian's CA certificates rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ - ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR"; \ + ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR" + # smoke test - openssl version; \ - \ +RUN openssl version + +FROM openssl-builder as erlang-builder + +RUN set -eux; \ OTP_SOURCE_URL="https://github.com/erlang/otp/releases/download/OTP-$OTP_VERSION/otp_src_$OTP_VERSION.tar.gz"; \ OTP_PATH="/usr/local/src/otp-$OTP_VERSION"; \ \ @@ -118,7 +103,6 @@ RUN set -eux; \ # ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation cd "$OTP_PATH"; \ export ERL_TOP="$OTP_PATH"; \ - ./otp_build autoconf; \ CFLAGS="$(dpkg-buildflags --get CFLAGS)"; export CFLAGS; \ # add -rpath to avoid conflicts between our OpenSSL's "libssl.so" and the libssl package by making sure /usr/local/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) export CFLAGS="$CFLAGS -Wl,-rpath=/usr/local/lib"; \ @@ -164,37 +148,39 @@ RUN set -eux; \ --without-wx \ $jitFlag \ ; \ + \ # Compile & install Erlang/OTP make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ make install; \ - cd ..; \ - rm -rf \ - "$OTP_PATH"* \ - /usr/local/lib/erlang/lib/*/examples \ - /usr/local/lib/erlang/lib/*/src \ - ; \ - \ -# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies - apt-mark auto '.*' > /dev/null; \ - [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \ - find /usr/local -type f -executable -exec ldd '{}' ';' \ - | awk '/=>/ { print $(NF-1) }' \ - | sort -u \ - | xargs -r dpkg-query --search \ - | cut -d: -f1 \ - | sort -u \ - | xargs -r apt-mark manual \ - ; \ - apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ \ -# Check that OpenSSL still works after purging build dependencies - openssl version; \ +# Remove unnecessary files + find /usr/local/lib/erlang -type d -name examples -exec rm -rf '{}' +; \ + find /usr/local/lib/erlang -type d -name src -exec rm -rf '{}' +; \ + find /usr/local/lib/erlang -type d -name include -exec rm -rf '{}' + + # Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly - erl -noshell -eval 'io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' +RUN erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' + +FROM ubuntu:20.04 + +COPY --from=erlang-builder /usr/local/bin/ /usr/local/bin/ +COPY --from=erlang-builder /usr/local/etc/ssl/ /usr/local/etc/ssl/ +COPY --from=erlang-builder /usr/local/lib/ /usr/local/lib/ ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq -# Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM + RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private /usr/local/etc/ssl; \ + \ +# Check that OpenSSL still works after copying from previous builder + ldconfig; \ + openssl version; \ + \ +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly + erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().'; \ + \ +# Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM groupadd --gid 999 --system rabbitmq; \ useradd --uid 999 --system --home-dir "$RABBITMQ_DATA_DIR" --gid rabbitmq rabbitmq; \ mkdir -p "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ @@ -213,11 +199,20 @@ ENV PATH=$RABBITMQ_HOME/sbin:$PATH # Install RabbitMQ RUN set -eux; \ - \ - savedAptMark="$(apt-mark showmanual)"; \ + export DEBIAN_FRONTEND=noninteractive; \ apt-get update; \ apt-get install --yes --no-install-recommends \ ca-certificates \ +# grab gosu for easy step-down from root + gosu \ +# Bring in tzdata so users could set the timezones through the environment + tzdata \ + ; \ +# verify that the "gosu" binary works + gosu nobody true; \ + \ + savedAptMark="$(apt-mark showmanual)"; \ + apt-get install --yes --no-install-recommends \ gnupg \ wget \ xz-utils \ diff --git a/3.11/alpine/Dockerfile b/3.11/alpine/Dockerfile index 0c73d1ae..a6c1652f 100644 --- a/3.11/alpine/Dockerfile +++ b/3.11/alpine/Dockerfile @@ -5,17 +5,18 @@ # # Alpine Linux is not officially supported by the RabbitMQ team -- use at your own risk! -FROM alpine:3.17 +FROM alpine:3.17 as build-base RUN apk add --no-cache \ -# grab su-exec for easy step-down from root - 'su-exec>=0.2' \ -# bash for docker-entrypoint.sh - bash \ -# "ps" for "rabbitmqctl wait" (https://github.com/docker-library/rabbitmq/issues/162) - procps \ -# Bring in tzdata so users could set the timezones through the environment - tzdata + build-base \ + dpkg-dev \ + dpkg \ + gnupg \ + libc-dev \ + linux-headers \ + ncurses-dev + +FROM build-base as openssl-builder # Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally ARG PGP_KEYSERVER=keyserver.ubuntu.com @@ -40,26 +41,13 @@ ENV OTP_SOURCE_SHA256="5442dea694e7555d479d80bc81f1428020639c258f8e40b2052732d1c # gnupg: Required to verify OpenSSL artefacts # libncurses5-dev: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli RUN set -eux; \ - \ - apk add --no-cache --virtual .build-deps \ - autoconf \ - dpkg-dev dpkg \ - g++ \ - gcc \ - gnupg \ - libc-dev \ - linux-headers \ - make \ - ncurses-dev \ - ; \ +# /usr/local/src doesn't exist in Alpine by default + mkdir -p /usr/local/src; \ \ OPENSSL_SOURCE_URL="https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz"; \ OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ OPENSSL_CONFIG_DIR=/usr/local/etc/ssl; \ \ -# /usr/local/src doesn't exist in Alpine by default - mkdir /usr/local/src; \ - \ # Required by the crypto & ssl Erlang/OTP applications wget --output-document "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_SOURCE_URL.asc"; \ wget --output-document "$OPENSSL_PATH.tar.gz" "$OPENSSL_SOURCE_URL"; \ @@ -89,13 +77,18 @@ RUN set -eux; \ # Compile, install OpenSSL, verify that the command-line works & development headers are present make -j "$(getconf _NPROCESSORS_ONLN)"; \ make install_sw install_ssldirs; \ - cd ..; \ - rm -rf "$OPENSSL_PATH"*; \ # use Alpine's CA certificates rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ - ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR"; \ + ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR" + # smoke test - openssl version; \ +RUN openssl version + +FROM openssl-builder as erlang-builder + +RUN set -eux; \ +# /usr/local/src doesn't exist in Alpine by default + mkdir -p /usr/local/src; \ \ OTP_SOURCE_URL="https://github.com/erlang/otp/releases/download/OTP-$OTP_VERSION/otp_src_$OTP_VERSION.tar.gz"; \ OTP_PATH="/usr/local/src/otp-$OTP_VERSION"; \ @@ -111,7 +104,6 @@ RUN set -eux; \ # ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation cd "$OTP_PATH"; \ export ERL_TOP="$OTP_PATH"; \ - ./otp_build autoconf; \ export CFLAGS='-g -O2'; \ # add -rpath to avoid conflicts between our OpenSSL's "libssl.so" and the libssl package by making sure /usr/local/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) export CFLAGS="$CFLAGS -Wl,-rpath=/usr/local/lib"; \ @@ -160,36 +152,59 @@ RUN set -eux; \ # Compile & install Erlang/OTP make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ make install; \ - cd ..; \ - rm -rf \ - "$OTP_PATH"* \ - /usr/local/lib/erlang/lib/*/examples \ - /usr/local/lib/erlang/lib/*/src \ - ; \ \ +# Remove unnecessary files + find /usr/local/lib/erlang -type d -name examples -exec rm -rf '{}' +; \ + find /usr/local/lib/erlang -type d -name src -exec rm -rf '{}' +; \ + find /usr/local/lib/erlang -type d -name include -exec rm -rf '{}' + + +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly +RUN erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' + +FROM alpine:3.17 + +COPY --from=erlang-builder /usr/local/bin/ /usr/local/bin/ +COPY --from=erlang-builder /usr/local/etc/ssl/ /usr/local/etc/ssl/ +COPY --from=erlang-builder /usr/local/lib/ /usr/local/lib/ + +ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq + +RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private /usr/local/etc/ssl; \ + \ +# Ensure run-time dependencies are installed runDeps="$( \ scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ | tr ',' '\n' \ | sort -u \ - | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ + | awk 'system("test -e /usr/local/lib/" $1) == 0 { next } { print "so:" $1 }' \ )"; \ apk add --no-cache --virtual .otp-run-deps $runDeps; \ - apk del --no-network .build-deps; \ \ -# Check that OpenSSL still works after purging build dependencies +# Check that OpenSSL still works after copying from previous builder openssl version; \ + \ # Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly - erl -noshell -eval 'io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' - -ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq + erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().'; \ + \ # Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM -RUN set -eux; \ addgroup -g 101 -S rabbitmq; \ adduser -u 100 -S -h "$RABBITMQ_DATA_DIR" -G rabbitmq rabbitmq; \ mkdir -p "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ chmod 777 "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ - ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie + ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie; \ + \ + apk add --no-cache \ +# grab su-exec for easy step-down from root + 'su-exec>=0.2' \ +# bash for docker-entrypoint.sh + bash \ +# "ps" for "rabbitmqctl wait" (https://github.com/docker-library/rabbitmq/issues/162) + procps \ +# Bring in tzdata so users could set the timezones through the environment + tzdata # Use the latest stable RabbitMQ release (https://www.rabbitmq.com/download.html) ENV RABBITMQ_VERSION 3.11.5 @@ -202,6 +217,8 @@ ENV PATH=$RABBITMQ_HOME/sbin:$PATH # Install RabbitMQ RUN set -eux; \ +# /usr/local/src doesn't exist in Alpine by default + mkdir -p /usr/local/src; \ \ apk add --no-cache --virtual .build-deps \ gnupg \ @@ -229,7 +246,7 @@ RUN set -eux; \ grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ \ - apk del .build-deps; \ + apk del --no-network .build-deps; \ \ # verify assumption of no stale cookies [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ diff --git a/3.11/ubuntu/Dockerfile b/3.11/ubuntu/Dockerfile index 4cf4c162..747df722 100644 --- a/3.11/ubuntu/Dockerfile +++ b/3.11/ubuntu/Dockerfile @@ -6,19 +6,18 @@ # The official Canonical Ubuntu Focal image is ideal from a security perspective, # especially for the enterprises that we, the RabbitMQ team, have to deal with -FROM ubuntu:20.04 +FROM ubuntu:20.04 as build-base RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends \ -# grab gosu for easy step-down from root - gosu \ -# Bring in tzdata so users could set the timezones through the environment - tzdata \ - ; \ - rm -rf /var/lib/apt/lists/*; \ -# verify that the "gosu" binary works - gosu nobody true + build-essential \ + ca-certificates \ + gnupg \ + libncurses5-dev \ + wget + +FROM build-base as openssl-builder # Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally ARG PGP_KEYSERVER=keyserver.ubuntu.com @@ -43,22 +42,6 @@ ENV OTP_SOURCE_SHA256="5442dea694e7555d479d80bc81f1428020639c258f8e40b2052732d1c # gnupg: Required to verify OpenSSL artefacts # libncurses5-dev: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli RUN set -eux; \ - \ - savedAptMark="$(apt-mark showmanual)"; \ - apt-get update; \ - apt-get install --yes --no-install-recommends \ - autoconf \ - ca-certificates \ - dpkg-dev \ - gcc \ - g++ \ - gnupg \ - libncurses5-dev \ - make \ - wget \ - ; \ - rm -rf /var/lib/apt/lists/*; \ - \ OPENSSL_SOURCE_URL="https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz"; \ OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ OPENSSL_CONFIG_DIR=/usr/local/etc/ssl; \ @@ -95,15 +78,17 @@ RUN set -eux; \ # Compile, install OpenSSL, verify that the command-line works & development headers are present make -j "$(getconf _NPROCESSORS_ONLN)"; \ make install_sw install_ssldirs; \ - cd ..; \ - rm -rf "$OPENSSL_PATH"*; \ ldconfig; \ # use Debian's CA certificates rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ - ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR"; \ + ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR" + # smoke test - openssl version; \ - \ +RUN openssl version + +FROM openssl-builder as erlang-builder + +RUN set -eux; \ OTP_SOURCE_URL="https://github.com/erlang/otp/releases/download/OTP-$OTP_VERSION/otp_src_$OTP_VERSION.tar.gz"; \ OTP_PATH="/usr/local/src/otp-$OTP_VERSION"; \ \ @@ -118,7 +103,6 @@ RUN set -eux; \ # ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation cd "$OTP_PATH"; \ export ERL_TOP="$OTP_PATH"; \ - ./otp_build autoconf; \ CFLAGS="$(dpkg-buildflags --get CFLAGS)"; export CFLAGS; \ # add -rpath to avoid conflicts between our OpenSSL's "libssl.so" and the libssl package by making sure /usr/local/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) export CFLAGS="$CFLAGS -Wl,-rpath=/usr/local/lib"; \ @@ -164,37 +148,39 @@ RUN set -eux; \ --without-wx \ $jitFlag \ ; \ + \ # Compile & install Erlang/OTP make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ make install; \ - cd ..; \ - rm -rf \ - "$OTP_PATH"* \ - /usr/local/lib/erlang/lib/*/examples \ - /usr/local/lib/erlang/lib/*/src \ - ; \ - \ -# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies - apt-mark auto '.*' > /dev/null; \ - [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \ - find /usr/local -type f -executable -exec ldd '{}' ';' \ - | awk '/=>/ { print $(NF-1) }' \ - | sort -u \ - | xargs -r dpkg-query --search \ - | cut -d: -f1 \ - | sort -u \ - | xargs -r apt-mark manual \ - ; \ - apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ \ -# Check that OpenSSL still works after purging build dependencies - openssl version; \ +# Remove unnecessary files + find /usr/local/lib/erlang -type d -name examples -exec rm -rf '{}' +; \ + find /usr/local/lib/erlang -type d -name src -exec rm -rf '{}' +; \ + find /usr/local/lib/erlang -type d -name include -exec rm -rf '{}' + + # Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly - erl -noshell -eval 'io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' +RUN erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' + +FROM ubuntu:20.04 + +COPY --from=erlang-builder /usr/local/bin/ /usr/local/bin/ +COPY --from=erlang-builder /usr/local/etc/ssl/ /usr/local/etc/ssl/ +COPY --from=erlang-builder /usr/local/lib/ /usr/local/lib/ ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq -# Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM + RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private /usr/local/etc/ssl; \ + \ +# Check that OpenSSL still works after copying from previous builder + ldconfig; \ + openssl version; \ + \ +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly + erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().'; \ + \ +# Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM groupadd --gid 999 --system rabbitmq; \ useradd --uid 999 --system --home-dir "$RABBITMQ_DATA_DIR" --gid rabbitmq rabbitmq; \ mkdir -p "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ @@ -213,11 +199,20 @@ ENV PATH=$RABBITMQ_HOME/sbin:$PATH # Install RabbitMQ RUN set -eux; \ - \ - savedAptMark="$(apt-mark showmanual)"; \ + export DEBIAN_FRONTEND=noninteractive; \ apt-get update; \ apt-get install --yes --no-install-recommends \ ca-certificates \ +# grab gosu for easy step-down from root + gosu \ +# Bring in tzdata so users could set the timezones through the environment + tzdata \ + ; \ +# verify that the "gosu" binary works + gosu nobody true; \ + \ + savedAptMark="$(apt-mark showmanual)"; \ + apt-get install --yes --no-install-recommends \ gnupg \ wget \ xz-utils \ diff --git a/3.9/alpine/Dockerfile b/3.9/alpine/Dockerfile index 76e4fb10..8d254141 100644 --- a/3.9/alpine/Dockerfile +++ b/3.9/alpine/Dockerfile @@ -5,17 +5,18 @@ # # Alpine Linux is not officially supported by the RabbitMQ team -- use at your own risk! -FROM alpine:3.17 +FROM alpine:3.17 as build-base RUN apk add --no-cache \ -# grab su-exec for easy step-down from root - 'su-exec>=0.2' \ -# bash for docker-entrypoint.sh - bash \ -# "ps" for "rabbitmqctl wait" (https://github.com/docker-library/rabbitmq/issues/162) - procps \ -# Bring in tzdata so users could set the timezones through the environment - tzdata + build-base \ + dpkg-dev \ + dpkg \ + gnupg \ + libc-dev \ + linux-headers \ + ncurses-dev + +FROM build-base as openssl-builder # Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally ARG PGP_KEYSERVER=keyserver.ubuntu.com @@ -40,26 +41,13 @@ ENV OTP_SOURCE_SHA256="5442dea694e7555d479d80bc81f1428020639c258f8e40b2052732d1c # gnupg: Required to verify OpenSSL artefacts # libncurses5-dev: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli RUN set -eux; \ - \ - apk add --no-cache --virtual .build-deps \ - autoconf \ - dpkg-dev dpkg \ - g++ \ - gcc \ - gnupg \ - libc-dev \ - linux-headers \ - make \ - ncurses-dev \ - ; \ +# /usr/local/src doesn't exist in Alpine by default + mkdir -p /usr/local/src; \ \ OPENSSL_SOURCE_URL="https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz"; \ OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ OPENSSL_CONFIG_DIR=/usr/local/etc/ssl; \ \ -# /usr/local/src doesn't exist in Alpine by default - mkdir /usr/local/src; \ - \ # Required by the crypto & ssl Erlang/OTP applications wget --output-document "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_SOURCE_URL.asc"; \ wget --output-document "$OPENSSL_PATH.tar.gz" "$OPENSSL_SOURCE_URL"; \ @@ -89,13 +77,18 @@ RUN set -eux; \ # Compile, install OpenSSL, verify that the command-line works & development headers are present make -j "$(getconf _NPROCESSORS_ONLN)"; \ make install_sw install_ssldirs; \ - cd ..; \ - rm -rf "$OPENSSL_PATH"*; \ # use Alpine's CA certificates rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ - ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR"; \ + ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR" + # smoke test - openssl version; \ +RUN openssl version + +FROM openssl-builder as erlang-builder + +RUN set -eux; \ +# /usr/local/src doesn't exist in Alpine by default + mkdir -p /usr/local/src; \ \ OTP_SOURCE_URL="https://github.com/erlang/otp/releases/download/OTP-$OTP_VERSION/otp_src_$OTP_VERSION.tar.gz"; \ OTP_PATH="/usr/local/src/otp-$OTP_VERSION"; \ @@ -111,7 +104,6 @@ RUN set -eux; \ # ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation cd "$OTP_PATH"; \ export ERL_TOP="$OTP_PATH"; \ - ./otp_build autoconf; \ export CFLAGS='-g -O2'; \ # add -rpath to avoid conflicts between our OpenSSL's "libssl.so" and the libssl package by making sure /usr/local/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) export CFLAGS="$CFLAGS -Wl,-rpath=/usr/local/lib"; \ @@ -160,36 +152,59 @@ RUN set -eux; \ # Compile & install Erlang/OTP make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ make install; \ - cd ..; \ - rm -rf \ - "$OTP_PATH"* \ - /usr/local/lib/erlang/lib/*/examples \ - /usr/local/lib/erlang/lib/*/src \ - ; \ \ +# Remove unnecessary files + find /usr/local/lib/erlang -type d -name examples -exec rm -rf '{}' +; \ + find /usr/local/lib/erlang -type d -name src -exec rm -rf '{}' +; \ + find /usr/local/lib/erlang -type d -name include -exec rm -rf '{}' + + +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly +RUN erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' + +FROM alpine:3.17 + +COPY --from=erlang-builder /usr/local/bin/ /usr/local/bin/ +COPY --from=erlang-builder /usr/local/etc/ssl/ /usr/local/etc/ssl/ +COPY --from=erlang-builder /usr/local/lib/ /usr/local/lib/ + +ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq + +RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private /usr/local/etc/ssl; \ + \ +# Ensure run-time dependencies are installed runDeps="$( \ scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ | tr ',' '\n' \ | sort -u \ - | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ + | awk 'system("test -e /usr/local/lib/" $1) == 0 { next } { print "so:" $1 }' \ )"; \ apk add --no-cache --virtual .otp-run-deps $runDeps; \ - apk del --no-network .build-deps; \ \ -# Check that OpenSSL still works after purging build dependencies +# Check that OpenSSL still works after copying from previous builder openssl version; \ + \ # Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly - erl -noshell -eval 'io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' - -ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq + erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().'; \ + \ # Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM -RUN set -eux; \ addgroup -g 101 -S rabbitmq; \ adduser -u 100 -S -h "$RABBITMQ_DATA_DIR" -G rabbitmq rabbitmq; \ mkdir -p "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ chmod 777 "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ - ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie + ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie; \ + \ + apk add --no-cache \ +# grab su-exec for easy step-down from root + 'su-exec>=0.2' \ +# bash for docker-entrypoint.sh + bash \ +# "ps" for "rabbitmqctl wait" (https://github.com/docker-library/rabbitmq/issues/162) + procps \ +# Bring in tzdata so users could set the timezones through the environment + tzdata # Use the latest stable RabbitMQ release (https://www.rabbitmq.com/download.html) ENV RABBITMQ_VERSION 3.9.27 @@ -202,6 +217,8 @@ ENV PATH=$RABBITMQ_HOME/sbin:$PATH # Install RabbitMQ RUN set -eux; \ +# /usr/local/src doesn't exist in Alpine by default + mkdir -p /usr/local/src; \ \ apk add --no-cache --virtual .build-deps \ gnupg \ @@ -229,7 +246,7 @@ RUN set -eux; \ grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ \ - apk del .build-deps; \ + apk del --no-network .build-deps; \ \ # verify assumption of no stale cookies [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ diff --git a/3.9/ubuntu/Dockerfile b/3.9/ubuntu/Dockerfile index 5fecf4f9..f99df984 100644 --- a/3.9/ubuntu/Dockerfile +++ b/3.9/ubuntu/Dockerfile @@ -6,19 +6,18 @@ # The official Canonical Ubuntu Focal image is ideal from a security perspective, # especially for the enterprises that we, the RabbitMQ team, have to deal with -FROM ubuntu:20.04 +FROM ubuntu:20.04 as build-base RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends \ -# grab gosu for easy step-down from root - gosu \ -# Bring in tzdata so users could set the timezones through the environment - tzdata \ - ; \ - rm -rf /var/lib/apt/lists/*; \ -# verify that the "gosu" binary works - gosu nobody true + build-essential \ + ca-certificates \ + gnupg \ + libncurses5-dev \ + wget + +FROM build-base as openssl-builder # Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally ARG PGP_KEYSERVER=keyserver.ubuntu.com @@ -43,22 +42,6 @@ ENV OTP_SOURCE_SHA256="5442dea694e7555d479d80bc81f1428020639c258f8e40b2052732d1c # gnupg: Required to verify OpenSSL artefacts # libncurses5-dev: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli RUN set -eux; \ - \ - savedAptMark="$(apt-mark showmanual)"; \ - apt-get update; \ - apt-get install --yes --no-install-recommends \ - autoconf \ - ca-certificates \ - dpkg-dev \ - gcc \ - g++ \ - gnupg \ - libncurses5-dev \ - make \ - wget \ - ; \ - rm -rf /var/lib/apt/lists/*; \ - \ OPENSSL_SOURCE_URL="https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz"; \ OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ OPENSSL_CONFIG_DIR=/usr/local/etc/ssl; \ @@ -95,15 +78,17 @@ RUN set -eux; \ # Compile, install OpenSSL, verify that the command-line works & development headers are present make -j "$(getconf _NPROCESSORS_ONLN)"; \ make install_sw install_ssldirs; \ - cd ..; \ - rm -rf "$OPENSSL_PATH"*; \ ldconfig; \ # use Debian's CA certificates rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ - ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR"; \ + ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR" + # smoke test - openssl version; \ - \ +RUN openssl version + +FROM openssl-builder as erlang-builder + +RUN set -eux; \ OTP_SOURCE_URL="https://github.com/erlang/otp/releases/download/OTP-$OTP_VERSION/otp_src_$OTP_VERSION.tar.gz"; \ OTP_PATH="/usr/local/src/otp-$OTP_VERSION"; \ \ @@ -118,7 +103,6 @@ RUN set -eux; \ # ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation cd "$OTP_PATH"; \ export ERL_TOP="$OTP_PATH"; \ - ./otp_build autoconf; \ CFLAGS="$(dpkg-buildflags --get CFLAGS)"; export CFLAGS; \ # add -rpath to avoid conflicts between our OpenSSL's "libssl.so" and the libssl package by making sure /usr/local/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) export CFLAGS="$CFLAGS -Wl,-rpath=/usr/local/lib"; \ @@ -164,37 +148,39 @@ RUN set -eux; \ --without-wx \ $jitFlag \ ; \ + \ # Compile & install Erlang/OTP make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ make install; \ - cd ..; \ - rm -rf \ - "$OTP_PATH"* \ - /usr/local/lib/erlang/lib/*/examples \ - /usr/local/lib/erlang/lib/*/src \ - ; \ - \ -# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies - apt-mark auto '.*' > /dev/null; \ - [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \ - find /usr/local -type f -executable -exec ldd '{}' ';' \ - | awk '/=>/ { print $(NF-1) }' \ - | sort -u \ - | xargs -r dpkg-query --search \ - | cut -d: -f1 \ - | sort -u \ - | xargs -r apt-mark manual \ - ; \ - apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ \ -# Check that OpenSSL still works after purging build dependencies - openssl version; \ +# Remove unnecessary files + find /usr/local/lib/erlang -type d -name examples -exec rm -rf '{}' +; \ + find /usr/local/lib/erlang -type d -name src -exec rm -rf '{}' +; \ + find /usr/local/lib/erlang -type d -name include -exec rm -rf '{}' + + # Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly - erl -noshell -eval 'io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' +RUN erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' + +FROM ubuntu:20.04 + +COPY --from=erlang-builder /usr/local/bin/ /usr/local/bin/ +COPY --from=erlang-builder /usr/local/etc/ssl/ /usr/local/etc/ssl/ +COPY --from=erlang-builder /usr/local/lib/ /usr/local/lib/ ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq -# Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM + RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private /usr/local/etc/ssl; \ + \ +# Check that OpenSSL still works after copying from previous builder + ldconfig; \ + openssl version; \ + \ +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly + erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().'; \ + \ +# Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM groupadd --gid 999 --system rabbitmq; \ useradd --uid 999 --system --home-dir "$RABBITMQ_DATA_DIR" --gid rabbitmq rabbitmq; \ mkdir -p "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ @@ -213,11 +199,20 @@ ENV PATH=$RABBITMQ_HOME/sbin:$PATH # Install RabbitMQ RUN set -eux; \ - \ - savedAptMark="$(apt-mark showmanual)"; \ + export DEBIAN_FRONTEND=noninteractive; \ apt-get update; \ apt-get install --yes --no-install-recommends \ ca-certificates \ +# grab gosu for easy step-down from root + gosu \ +# Bring in tzdata so users could set the timezones through the environment + tzdata \ + ; \ +# verify that the "gosu" binary works + gosu nobody true; \ + \ + savedAptMark="$(apt-mark showmanual)"; \ + apt-get install --yes --no-install-recommends \ gnupg \ wget \ xz-utils \ diff --git a/Dockerfile-alpine.template b/Dockerfile-alpine.template index 841f0240..c4d6ce82 100644 --- a/Dockerfile-alpine.template +++ b/Dockerfile-alpine.template @@ -1,15 +1,16 @@ # Alpine Linux is not officially supported by the RabbitMQ team -- use at your own risk! -FROM alpine:3.17 +FROM alpine:3.17 as build-base RUN apk add --no-cache \ -# grab su-exec for easy step-down from root - 'su-exec>=0.2' \ -# bash for docker-entrypoint.sh - bash \ -# "ps" for "rabbitmqctl wait" (https://github.com/docker-library/rabbitmq/issues/162) - procps \ -# Bring in tzdata so users could set the timezones through the environment - tzdata + build-base \ + dpkg-dev \ + dpkg \ + gnupg \ + libc-dev \ + linux-headers \ + ncurses-dev + +FROM build-base as openssl-builder # Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally ARG PGP_KEYSERVER=keyserver.ubuntu.com @@ -70,26 +71,13 @@ ENV OTP_SOURCE_SHA256="{{ .otp.sha256 }}" # gnupg: Required to verify OpenSSL artefacts # libncurses5-dev: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli RUN set -eux; \ - \ - apk add --no-cache --virtual .build-deps \ - autoconf \ - dpkg-dev dpkg \ - g++ \ - gcc \ - gnupg \ - libc-dev \ - linux-headers \ - make \ - ncurses-dev \ - ; \ +# /usr/local/src doesn't exist in Alpine by default + mkdir -p /usr/local/src; \ \ OPENSSL_SOURCE_URL="https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz"; \ OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ OPENSSL_CONFIG_DIR=/usr/local/etc/ssl; \ \ -# /usr/local/src doesn't exist in Alpine by default - mkdir /usr/local/src; \ - \ # Required by the crypto & ssl Erlang/OTP applications wget --output-document "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_SOURCE_URL.asc"; \ wget --output-document "$OPENSSL_PATH.tar.gz" "$OPENSSL_SOURCE_URL"; \ @@ -119,13 +107,18 @@ RUN set -eux; \ # Compile, install OpenSSL, verify that the command-line works & development headers are present make -j "$(getconf _NPROCESSORS_ONLN)"; \ make install_sw install_ssldirs; \ - cd ..; \ - rm -rf "$OPENSSL_PATH"*; \ # use Alpine's CA certificates rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ - ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR"; \ + ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR" + # smoke test - openssl version; \ +RUN openssl version + +FROM openssl-builder as erlang-builder + +RUN set -eux; \ +# /usr/local/src doesn't exist in Alpine by default + mkdir -p /usr/local/src; \ \ OTP_SOURCE_URL="https://github.com/erlang/otp/releases/download/OTP-$OTP_VERSION/otp_src_$OTP_VERSION.tar.gz"; \ OTP_PATH="/usr/local/src/otp-$OTP_VERSION"; \ @@ -141,7 +134,6 @@ RUN set -eux; \ # ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation cd "$OTP_PATH"; \ export ERL_TOP="$OTP_PATH"; \ - ./otp_build autoconf; \ export CFLAGS='-g -O2'; \ # add -rpath to avoid conflicts between our OpenSSL's "libssl.so" and the libssl package by making sure /usr/local/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) export CFLAGS="$CFLAGS -Wl,-rpath=/usr/local/lib"; \ @@ -190,36 +182,59 @@ RUN set -eux; \ # Compile & install Erlang/OTP make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ make install; \ - cd ..; \ - rm -rf \ - "$OTP_PATH"* \ - /usr/local/lib/erlang/lib/*/examples \ - /usr/local/lib/erlang/lib/*/src \ - ; \ \ +# Remove unnecessary files + find /usr/local/lib/erlang -type d -name examples -exec rm -rf '{}' +; \ + find /usr/local/lib/erlang -type d -name src -exec rm -rf '{}' +; \ + find /usr/local/lib/erlang -type d -name include -exec rm -rf '{}' + + +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly +RUN erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' + +FROM alpine:3.17 + +COPY --from=erlang-builder /usr/local/bin/ /usr/local/bin/ +COPY --from=erlang-builder /usr/local/etc/ssl/ /usr/local/etc/ssl/ +COPY --from=erlang-builder /usr/local/lib/ /usr/local/lib/ + +ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq + +RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private /usr/local/etc/ssl; \ + \ +# Ensure run-time dependencies are installed runDeps="$( \ scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ | tr ',' '\n' \ | sort -u \ - | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ + | awk 'system("test -e /usr/local/lib/" $1) == 0 { next } { print "so:" $1 }' \ )"; \ apk add --no-cache --virtual .otp-run-deps $runDeps; \ - apk del --no-network .build-deps; \ \ -# Check that OpenSSL still works after purging build dependencies +# Check that OpenSSL still works after copying from previous builder openssl version; \ + \ # Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly - erl -noshell -eval 'io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' - -ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq + erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().'; \ + \ # Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM -RUN set -eux; \ addgroup -g 101 -S rabbitmq; \ adduser -u 100 -S -h "$RABBITMQ_DATA_DIR" -G rabbitmq rabbitmq; \ mkdir -p "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ chmod 777 "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ - ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie + ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie; \ + \ + apk add --no-cache \ +# grab su-exec for easy step-down from root + 'su-exec>=0.2' \ +# bash for docker-entrypoint.sh + bash \ +# "ps" for "rabbitmqctl wait" (https://github.com/docker-library/rabbitmq/issues/162) + procps \ +# Bring in tzdata so users could set the timezones through the environment + tzdata # Use the latest stable RabbitMQ release (https://www.rabbitmq.com/download.html) ENV RABBITMQ_VERSION {{ .version }} @@ -232,6 +247,8 @@ ENV PATH=$RABBITMQ_HOME/sbin:$PATH # Install RabbitMQ RUN set -eux; \ +# /usr/local/src doesn't exist in Alpine by default + mkdir -p /usr/local/src; \ \ apk add --no-cache --virtual .build-deps \ gnupg \ @@ -259,7 +276,7 @@ RUN set -eux; \ grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ \ - apk del .build-deps; \ + apk del --no-network .build-deps; \ \ # verify assumption of no stale cookies [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ diff --git a/Dockerfile-ubuntu.template b/Dockerfile-ubuntu.template index 7702dcb8..a685c5aa 100644 --- a/Dockerfile-ubuntu.template +++ b/Dockerfile-ubuntu.template @@ -1,18 +1,17 @@ # The official Canonical Ubuntu Focal image is ideal from a security perspective, # especially for the enterprises that we, the RabbitMQ team, have to deal with -FROM ubuntu:20.04 +FROM ubuntu:20.04 as build-base RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends \ -# grab gosu for easy step-down from root - gosu \ -# Bring in tzdata so users could set the timezones through the environment - tzdata \ - ; \ - rm -rf /var/lib/apt/lists/*; \ -# verify that the "gosu" binary works - gosu nobody true + build-essential \ + ca-certificates \ + gnupg \ + libncurses5-dev \ + wget + +FROM build-base as openssl-builder # Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally ARG PGP_KEYSERVER=keyserver.ubuntu.com @@ -73,22 +72,6 @@ ENV OTP_SOURCE_SHA256="{{ .otp.sha256 }}" # gnupg: Required to verify OpenSSL artefacts # libncurses5-dev: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli RUN set -eux; \ - \ - savedAptMark="$(apt-mark showmanual)"; \ - apt-get update; \ - apt-get install --yes --no-install-recommends \ - autoconf \ - ca-certificates \ - dpkg-dev \ - gcc \ - g++ \ - gnupg \ - libncurses5-dev \ - make \ - wget \ - ; \ - rm -rf /var/lib/apt/lists/*; \ - \ OPENSSL_SOURCE_URL="https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz"; \ OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ OPENSSL_CONFIG_DIR=/usr/local/etc/ssl; \ @@ -125,15 +108,17 @@ RUN set -eux; \ # Compile, install OpenSSL, verify that the command-line works & development headers are present make -j "$(getconf _NPROCESSORS_ONLN)"; \ make install_sw install_ssldirs; \ - cd ..; \ - rm -rf "$OPENSSL_PATH"*; \ ldconfig; \ # use Debian's CA certificates rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ - ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR"; \ + ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR" + # smoke test - openssl version; \ - \ +RUN openssl version + +FROM openssl-builder as erlang-builder + +RUN set -eux; \ OTP_SOURCE_URL="https://github.com/erlang/otp/releases/download/OTP-$OTP_VERSION/otp_src_$OTP_VERSION.tar.gz"; \ OTP_PATH="/usr/local/src/otp-$OTP_VERSION"; \ \ @@ -148,7 +133,6 @@ RUN set -eux; \ # ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation cd "$OTP_PATH"; \ export ERL_TOP="$OTP_PATH"; \ - ./otp_build autoconf; \ CFLAGS="$(dpkg-buildflags --get CFLAGS)"; export CFLAGS; \ # add -rpath to avoid conflicts between our OpenSSL's "libssl.so" and the libssl package by making sure /usr/local/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) export CFLAGS="$CFLAGS -Wl,-rpath=/usr/local/lib"; \ @@ -194,37 +178,39 @@ RUN set -eux; \ --without-wx \ $jitFlag \ ; \ + \ # Compile & install Erlang/OTP make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ make install; \ - cd ..; \ - rm -rf \ - "$OTP_PATH"* \ - /usr/local/lib/erlang/lib/*/examples \ - /usr/local/lib/erlang/lib/*/src \ - ; \ - \ -# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies - apt-mark auto '.*' > /dev/null; \ - [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \ - find /usr/local -type f -executable -exec ldd '{}' ';' \ - | awk '/=>/ { print $(NF-1) }' \ - | sort -u \ - | xargs -r dpkg-query --search \ - | cut -d: -f1 \ - | sort -u \ - | xargs -r apt-mark manual \ - ; \ - apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ \ -# Check that OpenSSL still works after purging build dependencies - openssl version; \ +# Remove unnecessary files + find /usr/local/lib/erlang -type d -name examples -exec rm -rf '{}' +; \ + find /usr/local/lib/erlang -type d -name src -exec rm -rf '{}' +; \ + find /usr/local/lib/erlang -type d -name include -exec rm -rf '{}' + + # Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly - erl -noshell -eval 'io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' +RUN erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' + +FROM ubuntu:20.04 + +COPY --from=erlang-builder /usr/local/bin/ /usr/local/bin/ +COPY --from=erlang-builder /usr/local/etc/ssl/ /usr/local/etc/ssl/ +COPY --from=erlang-builder /usr/local/lib/ /usr/local/lib/ ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq -# Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM + RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private /usr/local/etc/ssl; \ + \ +# Check that OpenSSL still works after copying from previous builder + ldconfig; \ + openssl version; \ + \ +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly + erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().'; \ + \ +# Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM groupadd --gid 999 --system rabbitmq; \ useradd --uid 999 --system --home-dir "$RABBITMQ_DATA_DIR" --gid rabbitmq rabbitmq; \ mkdir -p "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ @@ -243,11 +229,20 @@ ENV PATH=$RABBITMQ_HOME/sbin:$PATH # Install RabbitMQ RUN set -eux; \ - \ - savedAptMark="$(apt-mark showmanual)"; \ + export DEBIAN_FRONTEND=noninteractive; \ apt-get update; \ apt-get install --yes --no-install-recommends \ ca-certificates \ +# grab gosu for easy step-down from root + gosu \ +# Bring in tzdata so users could set the timezones through the environment + tzdata \ + ; \ +# verify that the "gosu" binary works + gosu nobody true; \ + \ + savedAptMark="$(apt-mark showmanual)"; \ + apt-get install --yes --no-install-recommends \ gnupg \ wget \ xz-utils \ diff --git a/generate-stackbrew-library.sh b/generate-stackbrew-library.sh index d0707f48..9ff9b763 100755 --- a/generate-stackbrew-library.sh +++ b/generate-stackbrew-library.sh @@ -34,8 +34,11 @@ dirCommit() { fileCommit \ Dockerfile \ $(git show HEAD:./Dockerfile | awk ' - toupper($1) == "COPY" { + /^COPY/ { for (i = 2; i < NF; i++) { + if ($i ~ /^--from=/) { + next + } print $i } } @@ -48,13 +51,13 @@ getArches() { local officialImagesUrl='https://github.com/docker-library/official-images/raw/master/library/' eval "declare -g -A parentRepoToArches=( $( - find -name 'Dockerfile' -exec awk ' - toupper($1) == "FROM" && $2 !~ /^('"$repo"'|scratch|.*\/.*)(:|$)/ { + find -name Dockerfile -exec awk ' + /^FROM/ { + if (index($2, ":") > 0 && index($2, "'"$repo"'") == 0) { print "'"$officialImagesUrl"'" $2 } - ' '{}' + \ - | sort -u \ - | xargs bashbrew cat --format '[{{ .RepoName }}:{{ .TagName }}]="{{ join " " .TagEntry.Architectures }}"' + }' '{}' + | sort -u \ + | xargs bashbrew cat --format '[{{ .RepoName }}:{{ .TagName }}]="{{ join " " .TagEntry.Architectures }}"' ) )" } getArches 'rabbitmq' @@ -65,6 +68,7 @@ cat <<-EOH Maintainers: Tianon Gravi (@tianon), Joseph Ferguson (@yosifkit) GitRepo: https://github.com/docker-library/rabbitmq.git +Builder: buildkit EOH # prints "$2$1$3$1...$N" @@ -118,7 +122,13 @@ for version; do variantAliases=( "${variantAliases[@]//latest-/}" ) fi - variantParent="$(awk 'toupper($1) == "FROM" { print $2 }' "$dir/Dockerfile")" + variantParent="$(awk ' + /^FROM/ { + if (index($2, ":") > 0) { + print $2 + exit 0 + } + }' "$dir/Dockerfile")" variantArches="${parentRepoToArches[$variantParent]}" echo