diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..8e2ce923 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +/*/**/*.conf linguist-generated +/*/**/Dockerfile linguist-generated +/*/**/docker-entrypoint.sh linguist-generated +/Dockerfile*.template linguist-language=Dockerfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..b36e3dda --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,60 @@ +name: GitHub CI + +on: + pull_request: + push: + workflow_dispatch: + schedule: + - cron: 0 0 * * 0 + +defaults: + run: + shell: 'bash -Eeuo pipefail -x {0}' + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +jobs: + + generate-jobs: + name: Generate Jobs + runs-on: ubuntu-latest + outputs: + strategy: ${{ steps.generate-jobs.outputs.strategy }} + steps: + - uses: actions/checkout@v4 + - uses: docker-library/bashbrew@HEAD + - id: generate-jobs + name: Generate Jobs + run: | + strategy="$("$BASHBREW_SCRIPTS/github-actions/generate.sh")" + + strategy="$("$BASHBREW_SCRIPTS/github-actions/munge-i386.sh" -c <<<"$strategy")" + + strategy="$(jq -c '.matrix.include |= [ .[] | select(.name | (test("i386") | not) or test("alpine")) ]' <<<"$strategy")" # Ubuntu no longer supports i386 (so we can only build test Alpine there; qemu-user-static is too slow for other arches) + + EOF="EOF-$RANDOM-$RANDOM-$RANDOM" + echo "strategy<<$EOF" >> "$GITHUB_OUTPUT" + jq <<<"$strategy" . | tee -a "$GITHUB_OUTPUT" + echo "$EOF" >> "$GITHUB_OUTPUT" + + test: + needs: generate-jobs + strategy: ${{ fromJson(needs.generate-jobs.outputs.strategy) }} + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - name: Prepare Environment + run: ${{ matrix.runs.prepare }} + - name: Pull Dependencies + run: ${{ matrix.runs.pull }} + - name: Build ${{ matrix.name }} + run: ${{ matrix.runs.build }} + - name: History ${{ matrix.name }} + run: ${{ matrix.runs.history }} + - name: Test ${{ matrix.name }} + run: ${{ matrix.runs.test }} + - name: '"docker images"' + run: ${{ matrix.runs.images }} diff --git a/.github/workflows/verify-templating.yml b/.github/workflows/verify-templating.yml new file mode 100644 index 00000000..e822ba6b --- /dev/null +++ b/.github/workflows/verify-templating.yml @@ -0,0 +1,19 @@ +name: Verify Templating + +on: + pull_request: + push: + workflow_dispatch: + +defaults: + run: + shell: 'bash -Eeuo pipefail -x {0}' + +jobs: + apply-templates: + name: Check For Uncomitted Changes + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: ./apply-templates.sh + - run: git diff --exit-code diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..d548f66d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.jq-template.awk diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0e8232ac..00000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -language: bash -services: docker - -install: - - git clone https://github.com/docker-library/official-images.git ~/official-images - -before_script: - - env | sort - - image='rabbitmq' - -script: - - docker build -t "$image" . - - ~/official-images/test/run.sh "$image" - - docker build -t "$image:management" management - - ~/official-images/test/run.sh "$image:management" - -after_script: - - docker images - -# vim:set et ts=2 sw=2: diff --git a/3.13/alpine/10-defaults.conf b/3.13/alpine/10-defaults.conf new file mode 100644 index 00000000..27973c74 --- /dev/null +++ b/3.13/alpine/10-defaults.conf @@ -0,0 +1,12 @@ +## DEFAULT SETTINGS ARE NOT MEANT TO BE TAKEN STRAIGHT INTO PRODUCTION +## see https://www.rabbitmq.com/configure.html for further information +## on configuring RabbitMQ + +## allow access to the guest user from anywhere on the network +## https://www.rabbitmq.com/access-control.html#loopback-users +## https://www.rabbitmq.com/production-checklist.html#users +loopback_users.guest = false + +## Send all logs to stdout/TTY. Necessary to see logs when running via +## a container +log.console = true diff --git a/3.13/alpine/20-management_agent.disable_metrics_collector.conf b/3.13/alpine/20-management_agent.disable_metrics_collector.conf new file mode 100644 index 00000000..6eb7a86c --- /dev/null +++ b/3.13/alpine/20-management_agent.disable_metrics_collector.conf @@ -0,0 +1,2 @@ +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +management_agent.disable_metrics_collector = true diff --git a/3.13/alpine/Dockerfile b/3.13/alpine/Dockerfile new file mode 100644 index 00000000..e02d1cb7 --- /dev/null +++ b/3.13/alpine/Dockerfile @@ -0,0 +1,325 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +# Alpine Linux is not officially supported by the RabbitMQ team -- use at your own risk! +FROM alpine:3.22 as build-base + +RUN apk add --no-cache \ + build-base \ + dpkg-dev \ + dpkg \ + gnupg \ + libc-dev \ + linux-headers \ + ncurses-dev + +FROM build-base as openssl-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +# Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally +ARG PGP_KEYSERVER=keyserver.ubuntu.com +# If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, +# 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 +# For context, see https://github.com/docker-library/official-images/issues/4252 + +ENV OPENSSL_VERSION 3.1.8 +ENV OPENSSL_SOURCE_SHA256="d319da6aecde3aa6f426b44bbf997406d95275c5c59ab6f6ef53caaa079f456f" +# https://www.openssl.org/source/ +ENV OPENSSL_PGP_KEY_IDS="0xBA5473A2B0587B07FB27CF2D216094DFD0CB81EF" + +ENV OTP_VERSION 26.2.5.15 +# TODO add PGP checking when the feature will be added to Erlang/OTP's build system +# https://erlang.org/pipermail/erlang-questions/2019-January/097067.html +ENV OTP_SOURCE_SHA256="28e6d63d82927f132d56289dd3c428ef8bce6bf2283c8549aa0a7afca1a8fe3b" + +# install openssl & erlang to a path that isn't auto-checked for libs to prevent accidental use by system packages +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl + +# Install dependencies required to build Erlang/OTP from source +# https://erlang.org/doc/installation_guide/INSTALL.html +# dpkg-dev: Required to set up host & build type when compiling Erlang/OTP +# 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; \ +# /usr/local/src doesn't exist in Alpine by default + mkdir -p /usr/local/src; \ + \ + OPENSSL_SOURCE_URL="https://github.com/openssl/openssl/releases/download/openssl-$OPENSSL_VERSION/openssl-$OPENSSL_VERSION.tar.gz"; \ + OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ + OPENSSL_CONFIG_DIR="$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# 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"; \ + export GNUPGHOME="$(mktemp -d)"; \ + for key in $OPENSSL_PGP_KEY_IDS; do \ + gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \ + done; \ + gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum -c -; \ + mkdir -p "$OPENSSL_PATH"; \ + tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \ + \ +# Configure OpenSSL for compilation + cd "$OPENSSL_PATH"; \ +# OpenSSL's "config" script uses a lot of "uname"-based target detection... + apkArch="$(apk --print-arch)"; \ +# https://dl-cdn.alpinelinux.org/alpine/edge/main/ + case "$apkArch" in \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L860 (look for "linux-" and "linux64-" keys) + aarch64) opensslMachine='linux-aarch64' ;; \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L736-L766 +# https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html + armhf) opensslMachine='linux-armv4'; opensslExtraConfig='-march=armv6+fp' ;; \ + armv7) opensslMachine='linux-armv4'; opensslExtraConfig='-march=armv7-a+fp' ;; \ + ppc64le) opensslMachine='linux-ppc64le' ;; \ + riscv64) opensslMachine='linux64-riscv64' ;; \ + s390x) opensslMachine='linux64-s390x' ;; \ + x86) opensslMachine='linux-x86' ;; \ + x86_64) opensslMachine='linux-x86_64' ;; \ + *) echo >&2 "error: unsupported arch: '$apkArch'"; exit 1 ;; \ + esac; \ + MACHINE="$opensslMachine" \ + RELEASE="4.x.y-z" \ + SYSTEM='Linux' \ + BUILD='???' \ + ./Configure \ + "$opensslMachine" \ + enable-fips \ + --prefix="$OPENSSL_INSTALL_PATH_PREFIX" \ + --openssldir="$OPENSSL_CONFIG_DIR" \ + --libdir="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ +# 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) + -Wl,-rpath="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ + ${opensslExtraConfig:-} \ + ; \ +# Compile, install OpenSSL, verify that the command-line works & development headers are present + make -j "$(getconf _NPROCESSORS_ONLN)"; \ + make install_sw install_ssldirs install_fips; \ +# 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" + +# smoke test +RUN $OPENSSL_INSTALL_PATH_PREFIX/bin/openssl version + +FROM openssl-builder as erlang-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +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"; \ + \ +# Download, verify & extract OTP_SOURCE + mkdir -p "$OTP_PATH"; \ + wget --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \ + echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum -c -; \ + tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \ + \ +# Configure Erlang/OTP for compilation, disable unused features & applications +# https://erlang.org/doc/applications.html +# ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation + cd "$OTP_PATH"; \ + export ERL_TOP="$OTP_PATH"; \ + export CFLAGS='-g -O2'; \ +# 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) + export CFLAGS="$CFLAGS -Wl,-rpath=$OPENSSL_INSTALL_PATH_PREFIX/lib"; \ + hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ + buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ + dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ +# JIT is only supported on amd64 + arm64; https://github.com/erlang/otp/blob/OTP-25.3.2.2/erts/configure#L24306-L24347 + jitFlag=; \ + case "$dpkgArch" in \ + amd64 | arm64) jitFlag='--enable-jit' ;; \ + esac; \ + ./configure \ + --prefix="$ERLANG_INSTALL_PATH_PREFIX" \ + --host="$hostArch" \ + --build="$buildArch" \ + --disable-hipe \ + --disable-sctp \ + --disable-silent-rules \ + --enable-builtin-zlib \ + --enable-clock-gettime \ + --enable-hybrid-heap \ + --enable-kernel-poll \ + --enable-smp-support \ + --enable-threads \ + --with-microstate-accounting=extra \ + --with-ssl="$OPENSSL_INSTALL_PATH_PREFIX" \ + --without-common_test \ + --without-debugger \ + --without-dialyzer \ + --without-diameter \ + --without-edoc \ + --without-erl_docgen \ + --without-et \ + --without-eunit \ + --without-ftp \ + --without-hipe \ + --without-jinterface \ + --without-megaco \ + --without-observer \ + --without-odbc \ + --without-reltool \ + --without-snmp \ + --without-ssh \ + --without-tftp \ + --without-wx \ + $jitFlag \ + ; \ +# Compile & install Erlang/OTP + make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ + make install; \ + \ +# Remove unnecessary files + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name examples -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name src -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name include -exec rm -rf '{}' + + +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$PATH +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 }' +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.22 + +# OPENSSL/ERLANG_INSTALL_PATH_PREFIX are defined in a different stage, so define them again +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl + +COPY --from=erlang-builder $ERLANG_INSTALL_PATH_PREFIX $ERLANG_INSTALL_PATH_PREFIX +COPY --from=openssl-builder $OPENSSL_INSTALL_PATH_PREFIX $OPENSSL_INSTALL_PATH_PREFIX + +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$OPENSSL_INSTALL_PATH_PREFIX/bin:$PATH + +ENV RABBITMQ_DATA_DIR /var/lib/rabbitmq + +RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# Ensure run-time dependencies are installed + runDeps="$( \ + scanelf --needed --nobanner --format '%n#p' --recursive $ERLANG_INSTALL_PATH_PREFIX $OPENSSL_INSTALL_PATH_PREFIX \ + | tr ',' '\n' \ + | sort -u \ + | grep -v '^$\|lib\(crypto\|ssl\)' \ + | awk 'system("test -e /usr/local/lib/" $1) == 0 { next } { print "so:" $1 }' \ + )"; \ + apk add --no-cache --virtual .otp-run-deps $runDeps; \ + \ +# Check that OpenSSL still works after copying from previous builder + sed -i.ORIG -e "/\.include.*fips/ s!.*!.include $OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf!" \ + -e '/# fips =/s/.*/fips = fips_sect/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/openssl.cnf"; \ + sed -i.ORIG -e '/^activate/s/^/#/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf"; \ + [ "$(command -v openssl)" = "$OPENSSL_INSTALL_PATH_PREFIX/bin/openssl" ]; \ + openssl version; \ + openssl version -d; \ + \ +# 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 + 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 1777 "$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; \ + \ + 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.13.7 +# https://www.rabbitmq.com/signatures.html#importing-gpg +ENV RABBITMQ_PGP_KEY_ID 0x0A9AF2115F4687BD29803A206B73A36E6026DFCA +ENV RABBITMQ_HOME /opt/rabbitmq + +# Add RabbitMQ to PATH +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 \ + xz \ + ; \ + \ + RABBITMQ_SOURCE_URL="https://github.com/rabbitmq/rabbitmq-server/releases/download/v$RABBITMQ_VERSION/rabbitmq-server-generic-unix-latest-toolchain-$RABBITMQ_VERSION.tar.xz"; \ + RABBITMQ_PATH="/usr/local/src/rabbitmq-$RABBITMQ_VERSION"; \ + \ + wget --output-document "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_SOURCE_URL.asc"; \ + wget --output-document "$RABBITMQ_PATH.tar.xz" "$RABBITMQ_SOURCE_URL"; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$RABBITMQ_PGP_KEY_ID"; \ + gpg --batch --verify "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_PATH.tar.xz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + \ + mkdir -p "$RABBITMQ_HOME"; \ + tar --extract --file "$RABBITMQ_PATH.tar.xz" --directory "$RABBITMQ_HOME" --strip-components 1; \ + rm -rf "$RABBITMQ_PATH"*; \ +# Do not default SYS_PREFIX to RABBITMQ_HOME, leave it empty + grep -qE '^SYS_PREFIX=\$\{RABBITMQ_HOME\}$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + sed -i 's/^SYS_PREFIX=.*$/SYS_PREFIX=/' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ + \ + apk del --no-network .build-deps; \ + \ +# verify assumption of no stale cookies + [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ +# Ensure RabbitMQ was installed correctly by running a few commands that do not depend on a running server, as the rabbitmq user +# If they all succeed, it's safe to assume that things have been set up correctly + su-exec rabbitmq rabbitmqctl help; \ + su-exec rabbitmq rabbitmqctl list_ciphers; \ + su-exec rabbitmq rabbitmq-plugins list; \ +# no stale cookies + rm "$RABBITMQ_DATA_DIR/.erlang.cookie" + +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +RUN su-exec rabbitmq rabbitmq-plugins enable --offline rabbitmq_prometheus + +# Added for backwards compatibility - users can simply COPY custom plugins to /plugins +RUN ln -sf /opt/rabbitmq/plugins /plugins + +# set home so that any `--user` knows where to put the erlang cookie +ENV HOME $RABBITMQ_DATA_DIR +# Hint that the data (a.k.a. home dir) dir should be separate volume +VOLUME $RABBITMQ_DATA_DIR + +# warning: the VM is running with native name encoding of latin1 which may cause Elixir to malfunction as it expects utf8. Please ensure your locale is set to UTF-8 (which can be verified by running "locale" in your shell) +# Setting all environment variables that control language preferences, behaviour differs - https://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html#The-LANGUAGE-variable +# https://docs.docker.com/samples/library/ubuntu/#locales +ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 + +COPY --chown=rabbitmq:rabbitmq 10-defaults.conf 20-management_agent.disable_metrics_collector.conf /etc/rabbitmq/conf.d/ +COPY docker-entrypoint.sh /usr/local/bin/ +ENTRYPOINT ["docker-entrypoint.sh"] + +EXPOSE 4369 5671 5672 15691 15692 25672 +CMD ["rabbitmq-server"] diff --git a/3.13/alpine/docker-entrypoint.sh b/3.13/alpine/docker-entrypoint.sh new file mode 100755 index 00000000..7ecad434 --- /dev/null +++ b/3.13/alpine/docker-entrypoint.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +set -euo pipefail + +# allow the container to be started with `--user` +if [[ "$1" == rabbitmq* ]] && [ "$(id -u)" = '0' ]; then + if [ "$1" = 'rabbitmq-server' ]; then + find /var/lib/rabbitmq \! -user rabbitmq -exec chown rabbitmq '{}' + + fi + + exec su-exec rabbitmq "$BASH_SOURCE" "$@" +fi + +deprecatedEnvVars=( + RABBITMQ_DEFAULT_PASS_FILE + RABBITMQ_DEFAULT_USER_FILE + RABBITMQ_MANAGEMENT_SSL_CACERTFILE + RABBITMQ_MANAGEMENT_SSL_CERTFILE + RABBITMQ_MANAGEMENT_SSL_DEPTH + RABBITMQ_MANAGEMENT_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_MANAGEMENT_SSL_KEYFILE + RABBITMQ_MANAGEMENT_SSL_VERIFY + RABBITMQ_SSL_CACERTFILE + RABBITMQ_SSL_CERTFILE + RABBITMQ_SSL_DEPTH + RABBITMQ_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_SSL_KEYFILE + RABBITMQ_SSL_VERIFY + RABBITMQ_VM_MEMORY_HIGH_WATERMARK +) +hasOldEnv= +for old in "${deprecatedEnvVars[@]}"; do + if [ -n "${!old:-}" ]; then + echo >&2 "error: $old is set but deprecated" + hasOldEnv=1 + fi +done +if [ -n "$hasOldEnv" ]; then + echo >&2 'error: deprecated environment variables detected' + echo >&2 + echo >&2 'Please use a configuration file instead; visit https://www.rabbitmq.com/configure.html to learn more' + echo >&2 + exit 1 +fi + +# if long and short hostnames are not the same, use long hostnames +if [ -z "${RABBITMQ_USE_LONGNAME:-}" ] && [ "$(hostname)" != "$(hostname -s)" ]; then + : "${RABBITMQ_USE_LONGNAME:=true}" +fi + +exec "$@" diff --git a/3.13/alpine/management/Dockerfile b/3.13/alpine/management/Dockerfile new file mode 100644 index 00000000..283386d8 --- /dev/null +++ b/3.13/alpine/management/Dockerfile @@ -0,0 +1,21 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +FROM rabbitmq:3.13-alpine + +RUN set -eux; \ + rabbitmq-plugins enable --offline rabbitmq_management; \ +# make sure the metrics collector is re-enabled (disabled in the base image for Prometheus-style metrics by default) + rm -f /etc/rabbitmq/conf.d/20-management_agent.disable_metrics_collector.conf; \ +# grab "rabbitmqadmin" from inside the "rabbitmq_management-X.Y.Z" plugin folder +# see https://github.com/docker-library/rabbitmq/issues/207 + cp /plugins/rabbitmq_management-*/priv/www/cli/rabbitmqadmin /usr/local/bin/rabbitmqadmin; \ + [ -s /usr/local/bin/rabbitmqadmin ]; \ + chmod +x /usr/local/bin/rabbitmqadmin; \ + apk add --no-cache python3; \ + rabbitmqadmin --version + +EXPOSE 15671 15672 diff --git a/3.13/ubuntu/10-defaults.conf b/3.13/ubuntu/10-defaults.conf new file mode 100644 index 00000000..27973c74 --- /dev/null +++ b/3.13/ubuntu/10-defaults.conf @@ -0,0 +1,12 @@ +## DEFAULT SETTINGS ARE NOT MEANT TO BE TAKEN STRAIGHT INTO PRODUCTION +## see https://www.rabbitmq.com/configure.html for further information +## on configuring RabbitMQ + +## allow access to the guest user from anywhere on the network +## https://www.rabbitmq.com/access-control.html#loopback-users +## https://www.rabbitmq.com/production-checklist.html#users +loopback_users.guest = false + +## Send all logs to stdout/TTY. Necessary to see logs when running via +## a container +log.console = true diff --git a/3.13/ubuntu/20-management_agent.disable_metrics_collector.conf b/3.13/ubuntu/20-management_agent.disable_metrics_collector.conf new file mode 100644 index 00000000..6eb7a86c --- /dev/null +++ b/3.13/ubuntu/20-management_agent.disable_metrics_collector.conf @@ -0,0 +1,2 @@ +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +management_agent.disable_metrics_collector = true diff --git a/3.13/ubuntu/Dockerfile b/3.13/ubuntu/Dockerfile new file mode 100644 index 00000000..01a5773f --- /dev/null +++ b/3.13/ubuntu/Dockerfile @@ -0,0 +1,326 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +# 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:24.04 as build-base + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + build-essential \ + ca-certificates \ + gnupg \ + libncurses5-dev \ + wget + +FROM build-base as openssl-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +# Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally +ARG PGP_KEYSERVER=keyserver.ubuntu.com +# If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, +# 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 +# For context, see https://github.com/docker-library/official-images/issues/4252 + +ENV OPENSSL_VERSION 3.1.8 +ENV OPENSSL_SOURCE_SHA256="d319da6aecde3aa6f426b44bbf997406d95275c5c59ab6f6ef53caaa079f456f" +# https://www.openssl.org/source/ +ENV OPENSSL_PGP_KEY_IDS="0xBA5473A2B0587B07FB27CF2D216094DFD0CB81EF" + +ENV OTP_VERSION 26.2.5.15 +# TODO add PGP checking when the feature will be added to Erlang/OTP's build system +# https://erlang.org/pipermail/erlang-questions/2019-January/097067.html +ENV OTP_SOURCE_SHA256="28e6d63d82927f132d56289dd3c428ef8bce6bf2283c8549aa0a7afca1a8fe3b" + +# install openssl & erlang to a path that isn't auto-checked for libs to prevent accidental use by system packages +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl + +# Install dependencies required to build Erlang/OTP from source +# https://erlang.org/doc/installation_guide/INSTALL.html +# dpkg-dev: Required to set up host & build type when compiling Erlang/OTP +# 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; \ + OPENSSL_SOURCE_URL="https://github.com/openssl/openssl/releases/download/openssl-$OPENSSL_VERSION/openssl-$OPENSSL_VERSION.tar.gz"; \ + OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ + OPENSSL_CONFIG_DIR="$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# Required by the crypto & ssl Erlang/OTP applications + wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_SOURCE_URL.asc"; \ + wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz" "$OPENSSL_SOURCE_URL"; \ + export GNUPGHOME="$(mktemp -d)"; \ + for key in $OPENSSL_PGP_KEY_IDS; do \ + gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \ + done; \ + gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum --check --strict -; \ + mkdir -p "$OPENSSL_PATH"; \ + tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \ + \ +# Configure OpenSSL for compilation + cd "$OPENSSL_PATH"; \ +# without specifying "--libdir", Erlang will fail during "crypto:supports()" looking for a "pthread_atfork" function that doesn't exist (but only on arm32v7/armhf??) +# OpenSSL's "config" script uses a lot of "uname"-based target detection... + dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ +# https://deb.debian.org/debian/dists/unstable/main/ + case "$dpkgArch" in \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L860 (look for "linux-" and "linux64-" keys) + amd64) opensslMachine='linux-x86_64' ;; \ + arm64) opensslMachine='linux-aarch64' ;; \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L736-L766 +# https://wiki.debian.org/ArchitectureSpecificsMemo#Architecture_baselines +# https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html + armhf) opensslMachine='linux-armv4'; opensslExtraConfig='-march=armv7-a+fp' ;; \ + i386) opensslMachine='linux-x86' ;; \ + ppc64el) opensslMachine='linux-ppc64le' ;; \ + riscv64) opensslMachine='linux64-riscv64' ;; \ + s390x) opensslMachine='linux64-s390x' ;; \ + *) echo >&2 "error: unsupported arch: '$apkArch'"; exit 1 ;; \ + esac; \ + MACHINE="$opensslMachine" \ + RELEASE="4.x.y-z" \ + SYSTEM='Linux' \ + BUILD='???' \ + ./Configure \ + "$opensslMachine" \ + enable-fips \ + --prefix="$OPENSSL_INSTALL_PATH_PREFIX" \ + --openssldir="$OPENSSL_CONFIG_DIR" \ + --libdir="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ +# 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) + -Wl,-rpath="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ + ${opensslExtraConfig:-} \ + ; \ +# Compile, install OpenSSL, verify that the command-line works & development headers are present + make -j "$(getconf _NPROCESSORS_ONLN)"; \ + make install_sw install_ssldirs install_fips; \ + 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" + +# smoke test +RUN $OPENSSL_INSTALL_PATH_PREFIX/bin/openssl version + +FROM openssl-builder as erlang-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +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"; \ + \ +# Download, verify & extract OTP_SOURCE + mkdir -p "$OTP_PATH"; \ + wget --progress dot:giga --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \ + echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum --check --strict -; \ + tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \ + \ +# backport https://github.com/erlang/otp/pull/7952 (applied upstream in OTP 27+) to fix time64 compilation issues on 32bit architectures +# see also https://bugs.debian.org/1067701, https://salsa.debian.org/erlang-team/packages/erlang/-/blob/89c4e190c6d1d7ee0133d9a8d6bf651ff1861e46/debian/patches/time64.patch + wget --output-document otp-time64.patch 'https://github.com/erlang/otp/pull/7952.patch?full_index=1'; \ + echo 'd1a0c0433a9a08c83171bedd438dd59bb336b40ec75f59edfc3a647b8b0c612d *otp-time64.patch' | sha256sum --check --strict -; \ + patch --input="$PWD/otp-time64.patch" --directory="$OTP_PATH" --strip=1; \ + rm otp-time64.patch; \ + \ +# Configure Erlang/OTP for compilation, disable unused features & applications +# https://erlang.org/doc/applications.html +# ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation + cd "$OTP_PATH"; \ + export ERL_TOP="$OTP_PATH"; \ + 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 "$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) + export CFLAGS="$CFLAGS -Wl,-rpath=$OPENSSL_INSTALL_PATH_PREFIX/lib"; \ + hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ + buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ + dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ +# JIT is only supported on amd64 + arm64; https://github.com/erlang/otp/blob/OTP-25.3.2.2/erts/configure#L24306-L24347 + jitFlag=; \ + case "$dpkgArch" in \ + amd64 | arm64) jitFlag='--enable-jit' ;; \ + esac; \ + ./configure \ + --prefix="$ERLANG_INSTALL_PATH_PREFIX" \ + --host="$hostArch" \ + --build="$buildArch" \ + --disable-hipe \ + --disable-sctp \ + --disable-silent-rules \ + --enable-builtin-zlib \ + --enable-clock-gettime \ + --enable-hybrid-heap \ + --enable-kernel-poll \ + --enable-smp-support \ + --enable-threads \ + --with-microstate-accounting=extra \ + --with-ssl="$OPENSSL_INSTALL_PATH_PREFIX" \ + --without-common_test \ + --without-debugger \ + --without-dialyzer \ + --without-diameter \ + --without-edoc \ + --without-erl_docgen \ + --without-et \ + --without-eunit \ + --without-ftp \ + --without-hipe \ + --without-jinterface \ + --without-megaco \ + --without-observer \ + --without-odbc \ + --without-reltool \ + --without-snmp \ + --without-ssh \ + --without-tftp \ + --without-wx \ + $jitFlag \ + ; \ + \ +# Compile & install Erlang/OTP + make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ + make install; \ + \ +# Remove unnecessary files + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name examples -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name src -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name include -exec rm -rf '{}' + + +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$PATH +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 }' +RUN erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' + +FROM ubuntu:24.04 + +# OPENSSL/ERLANG_INSTALL_PATH_PREFIX are defined in a different stage, so define them again +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl +COPY --from=erlang-builder $ERLANG_INSTALL_PATH_PREFIX $ERLANG_INSTALL_PATH_PREFIX +COPY --from=openssl-builder $OPENSSL_INSTALL_PATH_PREFIX $OPENSSL_INSTALL_PATH_PREFIX + +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$OPENSSL_INSTALL_PATH_PREFIX/bin:$PATH + +ENV RABBITMQ_DATA_DIR /var/lib/rabbitmq + +RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# Check that OpenSSL still works after copying from previous builder + ldconfig; \ + sed -i.ORIG -e "/\.include.*fips/ s!.*!.include $OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf!" \ + -e '/# fips =/s/.*/fips = fips_sect/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/openssl.cnf"; \ + sed -i.ORIG -e '/^activate/s/^/#/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf"; \ + [ "$(command -v openssl)" = "$OPENSSL_INSTALL_PATH_PREFIX/bin/openssl" ]; \ + openssl version; \ + openssl version -d; \ + \ +# 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; \ + chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ + chmod 1777 "$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 + +# Use the latest stable RabbitMQ release (https://www.rabbitmq.com/download.html) +ENV RABBITMQ_VERSION 3.13.7 +# https://www.rabbitmq.com/signatures.html#importing-gpg +ENV RABBITMQ_PGP_KEY_ID 0x0A9AF2115F4687BD29803A206B73A36E6026DFCA +ENV RABBITMQ_HOME /opt/rabbitmq + +# Add RabbitMQ to PATH +ENV PATH $RABBITMQ_HOME/sbin:$PATH + +# Install RabbitMQ +RUN set -eux; \ + 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 \ + ; \ + rm -rf /var/lib/apt/lists/*; \ + \ + RABBITMQ_SOURCE_URL="https://github.com/rabbitmq/rabbitmq-server/releases/download/v$RABBITMQ_VERSION/rabbitmq-server-generic-unix-latest-toolchain-$RABBITMQ_VERSION.tar.xz"; \ + RABBITMQ_PATH="/usr/local/src/rabbitmq-$RABBITMQ_VERSION"; \ + \ + wget --progress dot:giga --output-document "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_SOURCE_URL.asc"; \ + wget --progress dot:giga --output-document "$RABBITMQ_PATH.tar.xz" "$RABBITMQ_SOURCE_URL"; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$RABBITMQ_PGP_KEY_ID"; \ + gpg --batch --verify "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_PATH.tar.xz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + \ + mkdir -p "$RABBITMQ_HOME"; \ + tar --extract --file "$RABBITMQ_PATH.tar.xz" --directory "$RABBITMQ_HOME" --strip-components 1; \ + rm -rf "$RABBITMQ_PATH"*; \ +# Do not default SYS_PREFIX to RABBITMQ_HOME, leave it empty + grep -qE '^SYS_PREFIX=\$\{RABBITMQ_HOME\}$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + sed -i 's/^SYS_PREFIX=.*$/SYS_PREFIX=/' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ + \ + apt-mark auto '.*' > /dev/null; \ + apt-mark manual $savedAptMark; \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + \ +# verify assumption of no stale cookies + [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ +# Ensure RabbitMQ was installed correctly by running a few commands that do not depend on a running server, as the rabbitmq user +# If they all succeed, it's safe to assume that things have been set up correctly + gosu rabbitmq rabbitmqctl help; \ + gosu rabbitmq rabbitmqctl list_ciphers; \ + gosu rabbitmq rabbitmq-plugins list; \ +# no stale cookies + rm "$RABBITMQ_DATA_DIR/.erlang.cookie" + +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +RUN gosu rabbitmq rabbitmq-plugins enable --offline rabbitmq_prometheus + +# Added for backwards compatibility - users can simply COPY custom plugins to /plugins +RUN ln -sf /opt/rabbitmq/plugins /plugins + +# set home so that any `--user` knows where to put the erlang cookie +ENV HOME $RABBITMQ_DATA_DIR +# Hint that the data (a.k.a. home dir) dir should be separate volume +VOLUME $RABBITMQ_DATA_DIR + +# warning: the VM is running with native name encoding of latin1 which may cause Elixir to malfunction as it expects utf8. Please ensure your locale is set to UTF-8 (which can be verified by running "locale" in your shell) +# Setting all environment variables that control language preferences, behaviour differs - https://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html#The-LANGUAGE-variable +# https://docs.docker.com/samples/library/ubuntu/#locales +ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 + +COPY --chown=rabbitmq:rabbitmq 10-defaults.conf 20-management_agent.disable_metrics_collector.conf /etc/rabbitmq/conf.d/ +COPY docker-entrypoint.sh /usr/local/bin/ +ENTRYPOINT ["docker-entrypoint.sh"] + +EXPOSE 4369 5671 5672 15691 15692 25672 +CMD ["rabbitmq-server"] diff --git a/3.13/ubuntu/docker-entrypoint.sh b/3.13/ubuntu/docker-entrypoint.sh new file mode 100755 index 00000000..c1c55b6d --- /dev/null +++ b/3.13/ubuntu/docker-entrypoint.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +set -euo pipefail + +# allow the container to be started with `--user` +if [[ "$1" == rabbitmq* ]] && [ "$(id -u)" = '0' ]; then + if [ "$1" = 'rabbitmq-server' ]; then + find /var/lib/rabbitmq \! -user rabbitmq -exec chown rabbitmq '{}' + + fi + + exec gosu rabbitmq "$BASH_SOURCE" "$@" +fi + +deprecatedEnvVars=( + RABBITMQ_DEFAULT_PASS_FILE + RABBITMQ_DEFAULT_USER_FILE + RABBITMQ_MANAGEMENT_SSL_CACERTFILE + RABBITMQ_MANAGEMENT_SSL_CERTFILE + RABBITMQ_MANAGEMENT_SSL_DEPTH + RABBITMQ_MANAGEMENT_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_MANAGEMENT_SSL_KEYFILE + RABBITMQ_MANAGEMENT_SSL_VERIFY + RABBITMQ_SSL_CACERTFILE + RABBITMQ_SSL_CERTFILE + RABBITMQ_SSL_DEPTH + RABBITMQ_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_SSL_KEYFILE + RABBITMQ_SSL_VERIFY + RABBITMQ_VM_MEMORY_HIGH_WATERMARK +) +hasOldEnv= +for old in "${deprecatedEnvVars[@]}"; do + if [ -n "${!old:-}" ]; then + echo >&2 "error: $old is set but deprecated" + hasOldEnv=1 + fi +done +if [ -n "$hasOldEnv" ]; then + echo >&2 'error: deprecated environment variables detected' + echo >&2 + echo >&2 'Please use a configuration file instead; visit https://www.rabbitmq.com/configure.html to learn more' + echo >&2 + exit 1 +fi + +# if long and short hostnames are not the same, use long hostnames +if [ -z "${RABBITMQ_USE_LONGNAME:-}" ] && [ "$(hostname)" != "$(hostname -s)" ]; then + : "${RABBITMQ_USE_LONGNAME:=true}" +fi + +exec "$@" diff --git a/3.13/ubuntu/management/Dockerfile b/3.13/ubuntu/management/Dockerfile new file mode 100644 index 00000000..0ed0f059 --- /dev/null +++ b/3.13/ubuntu/management/Dockerfile @@ -0,0 +1,23 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +FROM rabbitmq:3.13 + +RUN set -eux; \ + rabbitmq-plugins enable --offline rabbitmq_management; \ +# make sure the metrics collector is re-enabled (disabled in the base image for Prometheus-style metrics by default) + rm -f /etc/rabbitmq/conf.d/20-management_agent.disable_metrics_collector.conf; \ +# grab "rabbitmqadmin" from inside the "rabbitmq_management-X.Y.Z" plugin folder +# see https://github.com/docker-library/rabbitmq/issues/207 + cp /plugins/rabbitmq_management-*/priv/www/cli/rabbitmqadmin /usr/local/bin/rabbitmqadmin; \ + [ -s /usr/local/bin/rabbitmqadmin ]; \ + chmod +x /usr/local/bin/rabbitmqadmin; \ + apt-get update; \ + apt-get install -y --no-install-recommends python3; \ + rm -rf /var/lib/apt/lists/*; \ + rabbitmqadmin --version + +EXPOSE 15671 15672 diff --git a/4.0/alpine/10-defaults.conf b/4.0/alpine/10-defaults.conf new file mode 100644 index 00000000..27973c74 --- /dev/null +++ b/4.0/alpine/10-defaults.conf @@ -0,0 +1,12 @@ +## DEFAULT SETTINGS ARE NOT MEANT TO BE TAKEN STRAIGHT INTO PRODUCTION +## see https://www.rabbitmq.com/configure.html for further information +## on configuring RabbitMQ + +## allow access to the guest user from anywhere on the network +## https://www.rabbitmq.com/access-control.html#loopback-users +## https://www.rabbitmq.com/production-checklist.html#users +loopback_users.guest = false + +## Send all logs to stdout/TTY. Necessary to see logs when running via +## a container +log.console = true diff --git a/4.0/alpine/20-management_agent.disable_metrics_collector.conf b/4.0/alpine/20-management_agent.disable_metrics_collector.conf new file mode 100644 index 00000000..6eb7a86c --- /dev/null +++ b/4.0/alpine/20-management_agent.disable_metrics_collector.conf @@ -0,0 +1,2 @@ +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +management_agent.disable_metrics_collector = true diff --git a/4.0/alpine/Dockerfile b/4.0/alpine/Dockerfile new file mode 100644 index 00000000..ba21c120 --- /dev/null +++ b/4.0/alpine/Dockerfile @@ -0,0 +1,325 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +# Alpine Linux is not officially supported by the RabbitMQ team -- use at your own risk! +FROM alpine:3.22 as build-base + +RUN apk add --no-cache \ + build-base \ + dpkg-dev \ + dpkg \ + gnupg \ + libc-dev \ + linux-headers \ + ncurses-dev + +FROM build-base as openssl-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +# Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally +ARG PGP_KEYSERVER=keyserver.ubuntu.com +# If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, +# run the build with a different PGP_KEYSERVER, e.g. docker build --tag rabbitmq:4.0 --build-arg PGP_KEYSERVER=pgpkeys.eu 4.0/ubuntu +# For context, see https://github.com/docker-library/official-images/issues/4252 + +ENV OPENSSL_VERSION 3.3.5 +ENV OPENSSL_SOURCE_SHA256="9d62c00a5a6903740c8703f0e006257f429d565d3b91ac1a9bd4a4c700002e01" +# https://www.openssl.org/source/ +ENV OPENSSL_PGP_KEY_IDS="0xBA5473A2B0587B07FB27CF2D216094DFD0CB81EF" + +ENV OTP_VERSION 27.3.4.3 +# TODO add PGP checking when the feature will be added to Erlang/OTP's build system +# https://erlang.org/pipermail/erlang-questions/2019-January/097067.html +ENV OTP_SOURCE_SHA256="597618c75890e8e606033bc8dbf6ec87fdf4e892c10b4912ae3c9a4f01384579" + +# install openssl & erlang to a path that isn't auto-checked for libs to prevent accidental use by system packages +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl + +# Install dependencies required to build Erlang/OTP from source +# https://erlang.org/doc/installation_guide/INSTALL.html +# dpkg-dev: Required to set up host & build type when compiling Erlang/OTP +# 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; \ +# /usr/local/src doesn't exist in Alpine by default + mkdir -p /usr/local/src; \ + \ + OPENSSL_SOURCE_URL="https://github.com/openssl/openssl/releases/download/openssl-$OPENSSL_VERSION/openssl-$OPENSSL_VERSION.tar.gz"; \ + OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ + OPENSSL_CONFIG_DIR="$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# 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"; \ + export GNUPGHOME="$(mktemp -d)"; \ + for key in $OPENSSL_PGP_KEY_IDS; do \ + gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \ + done; \ + gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum -c -; \ + mkdir -p "$OPENSSL_PATH"; \ + tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \ + \ +# Configure OpenSSL for compilation + cd "$OPENSSL_PATH"; \ +# OpenSSL's "config" script uses a lot of "uname"-based target detection... + apkArch="$(apk --print-arch)"; \ +# https://dl-cdn.alpinelinux.org/alpine/edge/main/ + case "$apkArch" in \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L860 (look for "linux-" and "linux64-" keys) + aarch64) opensslMachine='linux-aarch64' ;; \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L736-L766 +# https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html + armhf) opensslMachine='linux-armv4'; opensslExtraConfig='-march=armv6+fp' ;; \ + armv7) opensslMachine='linux-armv4'; opensslExtraConfig='-march=armv7-a+fp' ;; \ + ppc64le) opensslMachine='linux-ppc64le' ;; \ + riscv64) opensslMachine='linux64-riscv64' ;; \ + s390x) opensslMachine='linux64-s390x' ;; \ + x86) opensslMachine='linux-x86' ;; \ + x86_64) opensslMachine='linux-x86_64' ;; \ + *) echo >&2 "error: unsupported arch: '$apkArch'"; exit 1 ;; \ + esac; \ + MACHINE="$opensslMachine" \ + RELEASE="4.x.y-z" \ + SYSTEM='Linux' \ + BUILD='???' \ + ./Configure \ + "$opensslMachine" \ + enable-fips \ + --prefix="$OPENSSL_INSTALL_PATH_PREFIX" \ + --openssldir="$OPENSSL_CONFIG_DIR" \ + --libdir="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ +# 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) + -Wl,-rpath="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ + ${opensslExtraConfig:-} \ + ; \ +# Compile, install OpenSSL, verify that the command-line works & development headers are present + make -j "$(getconf _NPROCESSORS_ONLN)"; \ + make install_sw install_ssldirs install_fips; \ +# 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" + +# smoke test +RUN $OPENSSL_INSTALL_PATH_PREFIX/bin/openssl version + +FROM openssl-builder as erlang-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +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"; \ + \ +# Download, verify & extract OTP_SOURCE + mkdir -p "$OTP_PATH"; \ + wget --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \ + echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum -c -; \ + tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \ + \ +# Configure Erlang/OTP for compilation, disable unused features & applications +# https://erlang.org/doc/applications.html +# ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation + cd "$OTP_PATH"; \ + export ERL_TOP="$OTP_PATH"; \ + export CFLAGS='-g -O2'; \ +# 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) + export CFLAGS="$CFLAGS -Wl,-rpath=$OPENSSL_INSTALL_PATH_PREFIX/lib"; \ + hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ + buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ + dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ +# JIT is only supported on amd64 + arm64; https://github.com/erlang/otp/blob/OTP-25.3.2.2/erts/configure#L24306-L24347 + jitFlag=; \ + case "$dpkgArch" in \ + amd64 | arm64) jitFlag='--enable-jit' ;; \ + esac; \ + ./configure \ + --prefix="$ERLANG_INSTALL_PATH_PREFIX" \ + --host="$hostArch" \ + --build="$buildArch" \ + --disable-hipe \ + --disable-sctp \ + --disable-silent-rules \ + --enable-builtin-zlib \ + --enable-clock-gettime \ + --enable-hybrid-heap \ + --enable-kernel-poll \ + --enable-smp-support \ + --enable-threads \ + --with-microstate-accounting=extra \ + --with-ssl="$OPENSSL_INSTALL_PATH_PREFIX" \ + --without-common_test \ + --without-debugger \ + --without-dialyzer \ + --without-diameter \ + --without-edoc \ + --without-erl_docgen \ + --without-et \ + --without-eunit \ + --without-ftp \ + --without-hipe \ + --without-jinterface \ + --without-megaco \ + --without-observer \ + --without-odbc \ + --without-reltool \ + --without-snmp \ + --without-ssh \ + --without-tftp \ + --without-wx \ + $jitFlag \ + ; \ +# Compile & install Erlang/OTP + make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ + make install; \ + \ +# Remove unnecessary files + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name examples -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name src -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name include -exec rm -rf '{}' + + +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$PATH +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 }' +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.22 + +# OPENSSL/ERLANG_INSTALL_PATH_PREFIX are defined in a different stage, so define them again +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl + +COPY --from=erlang-builder $ERLANG_INSTALL_PATH_PREFIX $ERLANG_INSTALL_PATH_PREFIX +COPY --from=openssl-builder $OPENSSL_INSTALL_PATH_PREFIX $OPENSSL_INSTALL_PATH_PREFIX + +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$OPENSSL_INSTALL_PATH_PREFIX/bin:$PATH + +ENV RABBITMQ_DATA_DIR /var/lib/rabbitmq + +RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# Ensure run-time dependencies are installed + runDeps="$( \ + scanelf --needed --nobanner --format '%n#p' --recursive $ERLANG_INSTALL_PATH_PREFIX $OPENSSL_INSTALL_PATH_PREFIX \ + | tr ',' '\n' \ + | sort -u \ + | grep -v '^$\|lib\(crypto\|ssl\)' \ + | awk 'system("test -e /usr/local/lib/" $1) == 0 { next } { print "so:" $1 }' \ + )"; \ + apk add --no-cache --virtual .otp-run-deps $runDeps; \ + \ +# Check that OpenSSL still works after copying from previous builder + sed -i.ORIG -e "/\.include.*fips/ s!.*!.include $OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf!" \ + -e '/# fips =/s/.*/fips = fips_sect/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/openssl.cnf"; \ + sed -i.ORIG -e '/^activate/s/^/#/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf"; \ + [ "$(command -v openssl)" = "$OPENSSL_INSTALL_PATH_PREFIX/bin/openssl" ]; \ + openssl version; \ + openssl version -d; \ + \ +# 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 + 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 1777 "$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; \ + \ + 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 4.0.9 +# https://www.rabbitmq.com/signatures.html#importing-gpg +ENV RABBITMQ_PGP_KEY_ID 0x0A9AF2115F4687BD29803A206B73A36E6026DFCA +ENV RABBITMQ_HOME /opt/rabbitmq + +# Add RabbitMQ to PATH +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 \ + xz \ + ; \ + \ + RABBITMQ_SOURCE_URL="https://github.com/rabbitmq/rabbitmq-server/releases/download/v$RABBITMQ_VERSION/rabbitmq-server-generic-unix-latest-toolchain-$RABBITMQ_VERSION.tar.xz"; \ + RABBITMQ_PATH="/usr/local/src/rabbitmq-$RABBITMQ_VERSION"; \ + \ + wget --output-document "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_SOURCE_URL.asc"; \ + wget --output-document "$RABBITMQ_PATH.tar.xz" "$RABBITMQ_SOURCE_URL"; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$RABBITMQ_PGP_KEY_ID"; \ + gpg --batch --verify "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_PATH.tar.xz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + \ + mkdir -p "$RABBITMQ_HOME"; \ + tar --extract --file "$RABBITMQ_PATH.tar.xz" --directory "$RABBITMQ_HOME" --strip-components 1; \ + rm -rf "$RABBITMQ_PATH"*; \ +# Do not default SYS_PREFIX to RABBITMQ_HOME, leave it empty + grep -qE '^SYS_PREFIX=\$\{RABBITMQ_HOME\}$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + sed -i 's/^SYS_PREFIX=.*$/SYS_PREFIX=/' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ + \ + apk del --no-network .build-deps; \ + \ +# verify assumption of no stale cookies + [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ +# Ensure RabbitMQ was installed correctly by running a few commands that do not depend on a running server, as the rabbitmq user +# If they all succeed, it's safe to assume that things have been set up correctly + su-exec rabbitmq rabbitmqctl help; \ + su-exec rabbitmq rabbitmqctl list_ciphers; \ + su-exec rabbitmq rabbitmq-plugins list; \ +# no stale cookies + rm "$RABBITMQ_DATA_DIR/.erlang.cookie" + +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +RUN su-exec rabbitmq rabbitmq-plugins enable --offline rabbitmq_prometheus + +# Added for backwards compatibility - users can simply COPY custom plugins to /plugins +RUN ln -sf /opt/rabbitmq/plugins /plugins + +# set home so that any `--user` knows where to put the erlang cookie +ENV HOME $RABBITMQ_DATA_DIR +# Hint that the data (a.k.a. home dir) dir should be separate volume +VOLUME $RABBITMQ_DATA_DIR + +# warning: the VM is running with native name encoding of latin1 which may cause Elixir to malfunction as it expects utf8. Please ensure your locale is set to UTF-8 (which can be verified by running "locale" in your shell) +# Setting all environment variables that control language preferences, behaviour differs - https://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html#The-LANGUAGE-variable +# https://docs.docker.com/samples/library/ubuntu/#locales +ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 + +COPY --chown=rabbitmq:rabbitmq 10-defaults.conf 20-management_agent.disable_metrics_collector.conf /etc/rabbitmq/conf.d/ +COPY docker-entrypoint.sh /usr/local/bin/ +ENTRYPOINT ["docker-entrypoint.sh"] + +EXPOSE 4369 5671 5672 15691 15692 25672 +CMD ["rabbitmq-server"] diff --git a/4.0/alpine/docker-entrypoint.sh b/4.0/alpine/docker-entrypoint.sh new file mode 100755 index 00000000..7ecad434 --- /dev/null +++ b/4.0/alpine/docker-entrypoint.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +set -euo pipefail + +# allow the container to be started with `--user` +if [[ "$1" == rabbitmq* ]] && [ "$(id -u)" = '0' ]; then + if [ "$1" = 'rabbitmq-server' ]; then + find /var/lib/rabbitmq \! -user rabbitmq -exec chown rabbitmq '{}' + + fi + + exec su-exec rabbitmq "$BASH_SOURCE" "$@" +fi + +deprecatedEnvVars=( + RABBITMQ_DEFAULT_PASS_FILE + RABBITMQ_DEFAULT_USER_FILE + RABBITMQ_MANAGEMENT_SSL_CACERTFILE + RABBITMQ_MANAGEMENT_SSL_CERTFILE + RABBITMQ_MANAGEMENT_SSL_DEPTH + RABBITMQ_MANAGEMENT_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_MANAGEMENT_SSL_KEYFILE + RABBITMQ_MANAGEMENT_SSL_VERIFY + RABBITMQ_SSL_CACERTFILE + RABBITMQ_SSL_CERTFILE + RABBITMQ_SSL_DEPTH + RABBITMQ_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_SSL_KEYFILE + RABBITMQ_SSL_VERIFY + RABBITMQ_VM_MEMORY_HIGH_WATERMARK +) +hasOldEnv= +for old in "${deprecatedEnvVars[@]}"; do + if [ -n "${!old:-}" ]; then + echo >&2 "error: $old is set but deprecated" + hasOldEnv=1 + fi +done +if [ -n "$hasOldEnv" ]; then + echo >&2 'error: deprecated environment variables detected' + echo >&2 + echo >&2 'Please use a configuration file instead; visit https://www.rabbitmq.com/configure.html to learn more' + echo >&2 + exit 1 +fi + +# if long and short hostnames are not the same, use long hostnames +if [ -z "${RABBITMQ_USE_LONGNAME:-}" ] && [ "$(hostname)" != "$(hostname -s)" ]; then + : "${RABBITMQ_USE_LONGNAME:=true}" +fi + +exec "$@" diff --git a/4.0/alpine/management/Dockerfile b/4.0/alpine/management/Dockerfile new file mode 100644 index 00000000..f939d7a4 --- /dev/null +++ b/4.0/alpine/management/Dockerfile @@ -0,0 +1,21 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +FROM rabbitmq:4.0-alpine + +RUN set -eux; \ + rabbitmq-plugins enable --offline rabbitmq_management; \ +# make sure the metrics collector is re-enabled (disabled in the base image for Prometheus-style metrics by default) + rm -f /etc/rabbitmq/conf.d/20-management_agent.disable_metrics_collector.conf; \ +# grab "rabbitmqadmin" from inside the "rabbitmq_management-X.Y.Z" plugin folder +# see https://github.com/docker-library/rabbitmq/issues/207 + cp /plugins/rabbitmq_management-*/priv/www/cli/rabbitmqadmin /usr/local/bin/rabbitmqadmin; \ + [ -s /usr/local/bin/rabbitmqadmin ]; \ + chmod +x /usr/local/bin/rabbitmqadmin; \ + apk add --no-cache python3; \ + rabbitmqadmin --version + +EXPOSE 15671 15672 diff --git a/4.0/ubuntu/10-defaults.conf b/4.0/ubuntu/10-defaults.conf new file mode 100644 index 00000000..27973c74 --- /dev/null +++ b/4.0/ubuntu/10-defaults.conf @@ -0,0 +1,12 @@ +## DEFAULT SETTINGS ARE NOT MEANT TO BE TAKEN STRAIGHT INTO PRODUCTION +## see https://www.rabbitmq.com/configure.html for further information +## on configuring RabbitMQ + +## allow access to the guest user from anywhere on the network +## https://www.rabbitmq.com/access-control.html#loopback-users +## https://www.rabbitmq.com/production-checklist.html#users +loopback_users.guest = false + +## Send all logs to stdout/TTY. Necessary to see logs when running via +## a container +log.console = true diff --git a/4.0/ubuntu/20-management_agent.disable_metrics_collector.conf b/4.0/ubuntu/20-management_agent.disable_metrics_collector.conf new file mode 100644 index 00000000..6eb7a86c --- /dev/null +++ b/4.0/ubuntu/20-management_agent.disable_metrics_collector.conf @@ -0,0 +1,2 @@ +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +management_agent.disable_metrics_collector = true diff --git a/4.0/ubuntu/Dockerfile b/4.0/ubuntu/Dockerfile new file mode 100644 index 00000000..fda8ba74 --- /dev/null +++ b/4.0/ubuntu/Dockerfile @@ -0,0 +1,319 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +# 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:24.04 as build-base + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + build-essential \ + ca-certificates \ + gnupg \ + libncurses5-dev \ + wget + +FROM build-base as openssl-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +# Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally +ARG PGP_KEYSERVER=keyserver.ubuntu.com +# If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, +# run the build with a different PGP_KEYSERVER, e.g. docker build --tag rabbitmq:4.0 --build-arg PGP_KEYSERVER=pgpkeys.eu 4.0/ubuntu +# For context, see https://github.com/docker-library/official-images/issues/4252 + +ENV OPENSSL_VERSION 3.3.5 +ENV OPENSSL_SOURCE_SHA256="9d62c00a5a6903740c8703f0e006257f429d565d3b91ac1a9bd4a4c700002e01" +# https://www.openssl.org/source/ +ENV OPENSSL_PGP_KEY_IDS="0xBA5473A2B0587B07FB27CF2D216094DFD0CB81EF" + +ENV OTP_VERSION 27.3.4.3 +# TODO add PGP checking when the feature will be added to Erlang/OTP's build system +# https://erlang.org/pipermail/erlang-questions/2019-January/097067.html +ENV OTP_SOURCE_SHA256="597618c75890e8e606033bc8dbf6ec87fdf4e892c10b4912ae3c9a4f01384579" + +# install openssl & erlang to a path that isn't auto-checked for libs to prevent accidental use by system packages +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl + +# Install dependencies required to build Erlang/OTP from source +# https://erlang.org/doc/installation_guide/INSTALL.html +# dpkg-dev: Required to set up host & build type when compiling Erlang/OTP +# 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; \ + OPENSSL_SOURCE_URL="https://github.com/openssl/openssl/releases/download/openssl-$OPENSSL_VERSION/openssl-$OPENSSL_VERSION.tar.gz"; \ + OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ + OPENSSL_CONFIG_DIR="$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# Required by the crypto & ssl Erlang/OTP applications + wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_SOURCE_URL.asc"; \ + wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz" "$OPENSSL_SOURCE_URL"; \ + export GNUPGHOME="$(mktemp -d)"; \ + for key in $OPENSSL_PGP_KEY_IDS; do \ + gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \ + done; \ + gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum --check --strict -; \ + mkdir -p "$OPENSSL_PATH"; \ + tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \ + \ +# Configure OpenSSL for compilation + cd "$OPENSSL_PATH"; \ +# without specifying "--libdir", Erlang will fail during "crypto:supports()" looking for a "pthread_atfork" function that doesn't exist (but only on arm32v7/armhf??) +# OpenSSL's "config" script uses a lot of "uname"-based target detection... + dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ +# https://deb.debian.org/debian/dists/unstable/main/ + case "$dpkgArch" in \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L860 (look for "linux-" and "linux64-" keys) + amd64) opensslMachine='linux-x86_64' ;; \ + arm64) opensslMachine='linux-aarch64' ;; \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L736-L766 +# https://wiki.debian.org/ArchitectureSpecificsMemo#Architecture_baselines +# https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html + armhf) opensslMachine='linux-armv4'; opensslExtraConfig='-march=armv7-a+fp' ;; \ + i386) opensslMachine='linux-x86' ;; \ + ppc64el) opensslMachine='linux-ppc64le' ;; \ + riscv64) opensslMachine='linux64-riscv64' ;; \ + s390x) opensslMachine='linux64-s390x' ;; \ + *) echo >&2 "error: unsupported arch: '$apkArch'"; exit 1 ;; \ + esac; \ + MACHINE="$opensslMachine" \ + RELEASE="4.x.y-z" \ + SYSTEM='Linux' \ + BUILD='???' \ + ./Configure \ + "$opensslMachine" \ + enable-fips \ + --prefix="$OPENSSL_INSTALL_PATH_PREFIX" \ + --openssldir="$OPENSSL_CONFIG_DIR" \ + --libdir="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ +# 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) + -Wl,-rpath="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ + ${opensslExtraConfig:-} \ + ; \ +# Compile, install OpenSSL, verify that the command-line works & development headers are present + make -j "$(getconf _NPROCESSORS_ONLN)"; \ + make install_sw install_ssldirs install_fips; \ + 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" + +# smoke test +RUN $OPENSSL_INSTALL_PATH_PREFIX/bin/openssl version + +FROM openssl-builder as erlang-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +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"; \ + \ +# Download, verify & extract OTP_SOURCE + mkdir -p "$OTP_PATH"; \ + wget --progress dot:giga --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \ + echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum --check --strict -; \ + tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \ + \ +# Configure Erlang/OTP for compilation, disable unused features & applications +# https://erlang.org/doc/applications.html +# ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation + cd "$OTP_PATH"; \ + export ERL_TOP="$OTP_PATH"; \ + 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 "$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) + export CFLAGS="$CFLAGS -Wl,-rpath=$OPENSSL_INSTALL_PATH_PREFIX/lib"; \ + hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ + buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ + dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ +# JIT is only supported on amd64 + arm64; https://github.com/erlang/otp/blob/OTP-25.3.2.2/erts/configure#L24306-L24347 + jitFlag=; \ + case "$dpkgArch" in \ + amd64 | arm64) jitFlag='--enable-jit' ;; \ + esac; \ + ./configure \ + --prefix="$ERLANG_INSTALL_PATH_PREFIX" \ + --host="$hostArch" \ + --build="$buildArch" \ + --disable-hipe \ + --disable-sctp \ + --disable-silent-rules \ + --enable-builtin-zlib \ + --enable-clock-gettime \ + --enable-hybrid-heap \ + --enable-kernel-poll \ + --enable-smp-support \ + --enable-threads \ + --with-microstate-accounting=extra \ + --with-ssl="$OPENSSL_INSTALL_PATH_PREFIX" \ + --without-common_test \ + --without-debugger \ + --without-dialyzer \ + --without-diameter \ + --without-edoc \ + --without-erl_docgen \ + --without-et \ + --without-eunit \ + --without-ftp \ + --without-hipe \ + --without-jinterface \ + --without-megaco \ + --without-observer \ + --without-odbc \ + --without-reltool \ + --without-snmp \ + --without-ssh \ + --without-tftp \ + --without-wx \ + $jitFlag \ + ; \ + \ +# Compile & install Erlang/OTP + make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ + make install; \ + \ +# Remove unnecessary files + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name examples -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name src -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name include -exec rm -rf '{}' + + +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$PATH +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 }' +RUN erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' + +FROM ubuntu:24.04 + +# OPENSSL/ERLANG_INSTALL_PATH_PREFIX are defined in a different stage, so define them again +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl +COPY --from=erlang-builder $ERLANG_INSTALL_PATH_PREFIX $ERLANG_INSTALL_PATH_PREFIX +COPY --from=openssl-builder $OPENSSL_INSTALL_PATH_PREFIX $OPENSSL_INSTALL_PATH_PREFIX + +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$OPENSSL_INSTALL_PATH_PREFIX/bin:$PATH + +ENV RABBITMQ_DATA_DIR /var/lib/rabbitmq + +RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# Check that OpenSSL still works after copying from previous builder + ldconfig; \ + sed -i.ORIG -e "/\.include.*fips/ s!.*!.include $OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf!" \ + -e '/# fips =/s/.*/fips = fips_sect/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/openssl.cnf"; \ + sed -i.ORIG -e '/^activate/s/^/#/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf"; \ + [ "$(command -v openssl)" = "$OPENSSL_INSTALL_PATH_PREFIX/bin/openssl" ]; \ + openssl version; \ + openssl version -d; \ + \ +# 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; \ + chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ + chmod 1777 "$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 + +# Use the latest stable RabbitMQ release (https://www.rabbitmq.com/download.html) +ENV RABBITMQ_VERSION 4.0.9 +# https://www.rabbitmq.com/signatures.html#importing-gpg +ENV RABBITMQ_PGP_KEY_ID 0x0A9AF2115F4687BD29803A206B73A36E6026DFCA +ENV RABBITMQ_HOME /opt/rabbitmq + +# Add RabbitMQ to PATH +ENV PATH $RABBITMQ_HOME/sbin:$PATH + +# Install RabbitMQ +RUN set -eux; \ + 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 \ + ; \ + rm -rf /var/lib/apt/lists/*; \ + \ + RABBITMQ_SOURCE_URL="https://github.com/rabbitmq/rabbitmq-server/releases/download/v$RABBITMQ_VERSION/rabbitmq-server-generic-unix-latest-toolchain-$RABBITMQ_VERSION.tar.xz"; \ + RABBITMQ_PATH="/usr/local/src/rabbitmq-$RABBITMQ_VERSION"; \ + \ + wget --progress dot:giga --output-document "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_SOURCE_URL.asc"; \ + wget --progress dot:giga --output-document "$RABBITMQ_PATH.tar.xz" "$RABBITMQ_SOURCE_URL"; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$RABBITMQ_PGP_KEY_ID"; \ + gpg --batch --verify "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_PATH.tar.xz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + \ + mkdir -p "$RABBITMQ_HOME"; \ + tar --extract --file "$RABBITMQ_PATH.tar.xz" --directory "$RABBITMQ_HOME" --strip-components 1; \ + rm -rf "$RABBITMQ_PATH"*; \ +# Do not default SYS_PREFIX to RABBITMQ_HOME, leave it empty + grep -qE '^SYS_PREFIX=\$\{RABBITMQ_HOME\}$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + sed -i 's/^SYS_PREFIX=.*$/SYS_PREFIX=/' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ + \ + apt-mark auto '.*' > /dev/null; \ + apt-mark manual $savedAptMark; \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + \ +# verify assumption of no stale cookies + [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ +# Ensure RabbitMQ was installed correctly by running a few commands that do not depend on a running server, as the rabbitmq user +# If they all succeed, it's safe to assume that things have been set up correctly + gosu rabbitmq rabbitmqctl help; \ + gosu rabbitmq rabbitmqctl list_ciphers; \ + gosu rabbitmq rabbitmq-plugins list; \ +# no stale cookies + rm "$RABBITMQ_DATA_DIR/.erlang.cookie" + +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +RUN gosu rabbitmq rabbitmq-plugins enable --offline rabbitmq_prometheus + +# Added for backwards compatibility - users can simply COPY custom plugins to /plugins +RUN ln -sf /opt/rabbitmq/plugins /plugins + +# set home so that any `--user` knows where to put the erlang cookie +ENV HOME $RABBITMQ_DATA_DIR +# Hint that the data (a.k.a. home dir) dir should be separate volume +VOLUME $RABBITMQ_DATA_DIR + +# warning: the VM is running with native name encoding of latin1 which may cause Elixir to malfunction as it expects utf8. Please ensure your locale is set to UTF-8 (which can be verified by running "locale" in your shell) +# Setting all environment variables that control language preferences, behaviour differs - https://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html#The-LANGUAGE-variable +# https://docs.docker.com/samples/library/ubuntu/#locales +ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 + +COPY --chown=rabbitmq:rabbitmq 10-defaults.conf 20-management_agent.disable_metrics_collector.conf /etc/rabbitmq/conf.d/ +COPY docker-entrypoint.sh /usr/local/bin/ +ENTRYPOINT ["docker-entrypoint.sh"] + +EXPOSE 4369 5671 5672 15691 15692 25672 +CMD ["rabbitmq-server"] diff --git a/4.0/ubuntu/docker-entrypoint.sh b/4.0/ubuntu/docker-entrypoint.sh new file mode 100755 index 00000000..c1c55b6d --- /dev/null +++ b/4.0/ubuntu/docker-entrypoint.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +set -euo pipefail + +# allow the container to be started with `--user` +if [[ "$1" == rabbitmq* ]] && [ "$(id -u)" = '0' ]; then + if [ "$1" = 'rabbitmq-server' ]; then + find /var/lib/rabbitmq \! -user rabbitmq -exec chown rabbitmq '{}' + + fi + + exec gosu rabbitmq "$BASH_SOURCE" "$@" +fi + +deprecatedEnvVars=( + RABBITMQ_DEFAULT_PASS_FILE + RABBITMQ_DEFAULT_USER_FILE + RABBITMQ_MANAGEMENT_SSL_CACERTFILE + RABBITMQ_MANAGEMENT_SSL_CERTFILE + RABBITMQ_MANAGEMENT_SSL_DEPTH + RABBITMQ_MANAGEMENT_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_MANAGEMENT_SSL_KEYFILE + RABBITMQ_MANAGEMENT_SSL_VERIFY + RABBITMQ_SSL_CACERTFILE + RABBITMQ_SSL_CERTFILE + RABBITMQ_SSL_DEPTH + RABBITMQ_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_SSL_KEYFILE + RABBITMQ_SSL_VERIFY + RABBITMQ_VM_MEMORY_HIGH_WATERMARK +) +hasOldEnv= +for old in "${deprecatedEnvVars[@]}"; do + if [ -n "${!old:-}" ]; then + echo >&2 "error: $old is set but deprecated" + hasOldEnv=1 + fi +done +if [ -n "$hasOldEnv" ]; then + echo >&2 'error: deprecated environment variables detected' + echo >&2 + echo >&2 'Please use a configuration file instead; visit https://www.rabbitmq.com/configure.html to learn more' + echo >&2 + exit 1 +fi + +# if long and short hostnames are not the same, use long hostnames +if [ -z "${RABBITMQ_USE_LONGNAME:-}" ] && [ "$(hostname)" != "$(hostname -s)" ]; then + : "${RABBITMQ_USE_LONGNAME:=true}" +fi + +exec "$@" diff --git a/4.0/ubuntu/management/Dockerfile b/4.0/ubuntu/management/Dockerfile new file mode 100644 index 00000000..da5b1b39 --- /dev/null +++ b/4.0/ubuntu/management/Dockerfile @@ -0,0 +1,23 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +FROM rabbitmq:4.0 + +RUN set -eux; \ + rabbitmq-plugins enable --offline rabbitmq_management; \ +# make sure the metrics collector is re-enabled (disabled in the base image for Prometheus-style metrics by default) + rm -f /etc/rabbitmq/conf.d/20-management_agent.disable_metrics_collector.conf; \ +# grab "rabbitmqadmin" from inside the "rabbitmq_management-X.Y.Z" plugin folder +# see https://github.com/docker-library/rabbitmq/issues/207 + cp /plugins/rabbitmq_management-*/priv/www/cli/rabbitmqadmin /usr/local/bin/rabbitmqadmin; \ + [ -s /usr/local/bin/rabbitmqadmin ]; \ + chmod +x /usr/local/bin/rabbitmqadmin; \ + apt-get update; \ + apt-get install -y --no-install-recommends python3; \ + rm -rf /var/lib/apt/lists/*; \ + rabbitmqadmin --version + +EXPOSE 15671 15672 diff --git a/4.1/alpine/10-defaults.conf b/4.1/alpine/10-defaults.conf new file mode 100644 index 00000000..27973c74 --- /dev/null +++ b/4.1/alpine/10-defaults.conf @@ -0,0 +1,12 @@ +## DEFAULT SETTINGS ARE NOT MEANT TO BE TAKEN STRAIGHT INTO PRODUCTION +## see https://www.rabbitmq.com/configure.html for further information +## on configuring RabbitMQ + +## allow access to the guest user from anywhere on the network +## https://www.rabbitmq.com/access-control.html#loopback-users +## https://www.rabbitmq.com/production-checklist.html#users +loopback_users.guest = false + +## Send all logs to stdout/TTY. Necessary to see logs when running via +## a container +log.console = true diff --git a/4.1/alpine/20-management_agent.disable_metrics_collector.conf b/4.1/alpine/20-management_agent.disable_metrics_collector.conf new file mode 100644 index 00000000..6eb7a86c --- /dev/null +++ b/4.1/alpine/20-management_agent.disable_metrics_collector.conf @@ -0,0 +1,2 @@ +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +management_agent.disable_metrics_collector = true diff --git a/4.1/alpine/Dockerfile b/4.1/alpine/Dockerfile new file mode 100644 index 00000000..f1228094 --- /dev/null +++ b/4.1/alpine/Dockerfile @@ -0,0 +1,325 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +# Alpine Linux is not officially supported by the RabbitMQ team -- use at your own risk! +FROM alpine:3.22 as build-base + +RUN apk add --no-cache \ + build-base \ + dpkg-dev \ + dpkg \ + gnupg \ + libc-dev \ + linux-headers \ + ncurses-dev + +FROM build-base as openssl-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +# Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally +ARG PGP_KEYSERVER=keyserver.ubuntu.com +# If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, +# run the build with a different PGP_KEYSERVER, e.g. docker build --tag rabbitmq:4.1 --build-arg PGP_KEYSERVER=pgpkeys.eu 4.1/ubuntu +# For context, see https://github.com/docker-library/official-images/issues/4252 + +ENV OPENSSL_VERSION 3.3.5 +ENV OPENSSL_SOURCE_SHA256="9d62c00a5a6903740c8703f0e006257f429d565d3b91ac1a9bd4a4c700002e01" +# https://www.openssl.org/source/ +ENV OPENSSL_PGP_KEY_IDS="0xBA5473A2B0587B07FB27CF2D216094DFD0CB81EF" + +ENV OTP_VERSION 27.3.4.3 +# TODO add PGP checking when the feature will be added to Erlang/OTP's build system +# https://erlang.org/pipermail/erlang-questions/2019-January/097067.html +ENV OTP_SOURCE_SHA256="597618c75890e8e606033bc8dbf6ec87fdf4e892c10b4912ae3c9a4f01384579" + +# install openssl & erlang to a path that isn't auto-checked for libs to prevent accidental use by system packages +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl + +# Install dependencies required to build Erlang/OTP from source +# https://erlang.org/doc/installation_guide/INSTALL.html +# dpkg-dev: Required to set up host & build type when compiling Erlang/OTP +# 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; \ +# /usr/local/src doesn't exist in Alpine by default + mkdir -p /usr/local/src; \ + \ + OPENSSL_SOURCE_URL="https://github.com/openssl/openssl/releases/download/openssl-$OPENSSL_VERSION/openssl-$OPENSSL_VERSION.tar.gz"; \ + OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ + OPENSSL_CONFIG_DIR="$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# 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"; \ + export GNUPGHOME="$(mktemp -d)"; \ + for key in $OPENSSL_PGP_KEY_IDS; do \ + gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \ + done; \ + gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum -c -; \ + mkdir -p "$OPENSSL_PATH"; \ + tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \ + \ +# Configure OpenSSL for compilation + cd "$OPENSSL_PATH"; \ +# OpenSSL's "config" script uses a lot of "uname"-based target detection... + apkArch="$(apk --print-arch)"; \ +# https://dl-cdn.alpinelinux.org/alpine/edge/main/ + case "$apkArch" in \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L860 (look for "linux-" and "linux64-" keys) + aarch64) opensslMachine='linux-aarch64' ;; \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L736-L766 +# https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html + armhf) opensslMachine='linux-armv4'; opensslExtraConfig='-march=armv6+fp' ;; \ + armv7) opensslMachine='linux-armv4'; opensslExtraConfig='-march=armv7-a+fp' ;; \ + ppc64le) opensslMachine='linux-ppc64le' ;; \ + riscv64) opensslMachine='linux64-riscv64' ;; \ + s390x) opensslMachine='linux64-s390x' ;; \ + x86) opensslMachine='linux-x86' ;; \ + x86_64) opensslMachine='linux-x86_64' ;; \ + *) echo >&2 "error: unsupported arch: '$apkArch'"; exit 1 ;; \ + esac; \ + MACHINE="$opensslMachine" \ + RELEASE="4.x.y-z" \ + SYSTEM='Linux' \ + BUILD='???' \ + ./Configure \ + "$opensslMachine" \ + enable-fips \ + --prefix="$OPENSSL_INSTALL_PATH_PREFIX" \ + --openssldir="$OPENSSL_CONFIG_DIR" \ + --libdir="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ +# 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) + -Wl,-rpath="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ + ${opensslExtraConfig:-} \ + ; \ +# Compile, install OpenSSL, verify that the command-line works & development headers are present + make -j "$(getconf _NPROCESSORS_ONLN)"; \ + make install_sw install_ssldirs install_fips; \ +# 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" + +# smoke test +RUN $OPENSSL_INSTALL_PATH_PREFIX/bin/openssl version + +FROM openssl-builder as erlang-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +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"; \ + \ +# Download, verify & extract OTP_SOURCE + mkdir -p "$OTP_PATH"; \ + wget --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \ + echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum -c -; \ + tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \ + \ +# Configure Erlang/OTP for compilation, disable unused features & applications +# https://erlang.org/doc/applications.html +# ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation + cd "$OTP_PATH"; \ + export ERL_TOP="$OTP_PATH"; \ + export CFLAGS='-g -O2'; \ +# 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) + export CFLAGS="$CFLAGS -Wl,-rpath=$OPENSSL_INSTALL_PATH_PREFIX/lib"; \ + hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ + buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ + dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ +# JIT is only supported on amd64 + arm64; https://github.com/erlang/otp/blob/OTP-25.3.2.2/erts/configure#L24306-L24347 + jitFlag=; \ + case "$dpkgArch" in \ + amd64 | arm64) jitFlag='--enable-jit' ;; \ + esac; \ + ./configure \ + --prefix="$ERLANG_INSTALL_PATH_PREFIX" \ + --host="$hostArch" \ + --build="$buildArch" \ + --disable-hipe \ + --disable-sctp \ + --disable-silent-rules \ + --enable-builtin-zlib \ + --enable-clock-gettime \ + --enable-hybrid-heap \ + --enable-kernel-poll \ + --enable-smp-support \ + --enable-threads \ + --with-microstate-accounting=extra \ + --with-ssl="$OPENSSL_INSTALL_PATH_PREFIX" \ + --without-common_test \ + --without-debugger \ + --without-dialyzer \ + --without-diameter \ + --without-edoc \ + --without-erl_docgen \ + --without-et \ + --without-eunit \ + --without-ftp \ + --without-hipe \ + --without-jinterface \ + --without-megaco \ + --without-observer \ + --without-odbc \ + --without-reltool \ + --without-snmp \ + --without-ssh \ + --without-tftp \ + --without-wx \ + $jitFlag \ + ; \ +# Compile & install Erlang/OTP + make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ + make install; \ + \ +# Remove unnecessary files + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name examples -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name src -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name include -exec rm -rf '{}' + + +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$PATH +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 }' +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.22 + +# OPENSSL/ERLANG_INSTALL_PATH_PREFIX are defined in a different stage, so define them again +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl + +COPY --from=erlang-builder $ERLANG_INSTALL_PATH_PREFIX $ERLANG_INSTALL_PATH_PREFIX +COPY --from=openssl-builder $OPENSSL_INSTALL_PATH_PREFIX $OPENSSL_INSTALL_PATH_PREFIX + +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$OPENSSL_INSTALL_PATH_PREFIX/bin:$PATH + +ENV RABBITMQ_DATA_DIR /var/lib/rabbitmq + +RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# Ensure run-time dependencies are installed + runDeps="$( \ + scanelf --needed --nobanner --format '%n#p' --recursive $ERLANG_INSTALL_PATH_PREFIX $OPENSSL_INSTALL_PATH_PREFIX \ + | tr ',' '\n' \ + | sort -u \ + | grep -v '^$\|lib\(crypto\|ssl\)' \ + | awk 'system("test -e /usr/local/lib/" $1) == 0 { next } { print "so:" $1 }' \ + )"; \ + apk add --no-cache --virtual .otp-run-deps $runDeps; \ + \ +# Check that OpenSSL still works after copying from previous builder + sed -i.ORIG -e "/\.include.*fips/ s!.*!.include $OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf!" \ + -e '/# fips =/s/.*/fips = fips_sect/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/openssl.cnf"; \ + sed -i.ORIG -e '/^activate/s/^/#/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf"; \ + [ "$(command -v openssl)" = "$OPENSSL_INSTALL_PATH_PREFIX/bin/openssl" ]; \ + openssl version; \ + openssl version -d; \ + \ +# 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 + 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 1777 "$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; \ + \ + 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 4.1.4 +# https://www.rabbitmq.com/signatures.html#importing-gpg +ENV RABBITMQ_PGP_KEY_ID 0x0A9AF2115F4687BD29803A206B73A36E6026DFCA +ENV RABBITMQ_HOME /opt/rabbitmq + +# Add RabbitMQ to PATH +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 \ + xz \ + ; \ + \ + RABBITMQ_SOURCE_URL="https://github.com/rabbitmq/rabbitmq-server/releases/download/v$RABBITMQ_VERSION/rabbitmq-server-generic-unix-latest-toolchain-$RABBITMQ_VERSION.tar.xz"; \ + RABBITMQ_PATH="/usr/local/src/rabbitmq-$RABBITMQ_VERSION"; \ + \ + wget --output-document "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_SOURCE_URL.asc"; \ + wget --output-document "$RABBITMQ_PATH.tar.xz" "$RABBITMQ_SOURCE_URL"; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$RABBITMQ_PGP_KEY_ID"; \ + gpg --batch --verify "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_PATH.tar.xz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + \ + mkdir -p "$RABBITMQ_HOME"; \ + tar --extract --file "$RABBITMQ_PATH.tar.xz" --directory "$RABBITMQ_HOME" --strip-components 1; \ + rm -rf "$RABBITMQ_PATH"*; \ +# Do not default SYS_PREFIX to RABBITMQ_HOME, leave it empty + grep -qE '^SYS_PREFIX=\$\{RABBITMQ_HOME\}$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + sed -i 's/^SYS_PREFIX=.*$/SYS_PREFIX=/' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ + \ + apk del --no-network .build-deps; \ + \ +# verify assumption of no stale cookies + [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ +# Ensure RabbitMQ was installed correctly by running a few commands that do not depend on a running server, as the rabbitmq user +# If they all succeed, it's safe to assume that things have been set up correctly + su-exec rabbitmq rabbitmqctl help; \ + su-exec rabbitmq rabbitmqctl list_ciphers; \ + su-exec rabbitmq rabbitmq-plugins list; \ +# no stale cookies + rm "$RABBITMQ_DATA_DIR/.erlang.cookie" + +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +RUN su-exec rabbitmq rabbitmq-plugins enable --offline rabbitmq_prometheus + +# Added for backwards compatibility - users can simply COPY custom plugins to /plugins +RUN ln -sf /opt/rabbitmq/plugins /plugins + +# set home so that any `--user` knows where to put the erlang cookie +ENV HOME $RABBITMQ_DATA_DIR +# Hint that the data (a.k.a. home dir) dir should be separate volume +VOLUME $RABBITMQ_DATA_DIR + +# warning: the VM is running with native name encoding of latin1 which may cause Elixir to malfunction as it expects utf8. Please ensure your locale is set to UTF-8 (which can be verified by running "locale" in your shell) +# Setting all environment variables that control language preferences, behaviour differs - https://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html#The-LANGUAGE-variable +# https://docs.docker.com/samples/library/ubuntu/#locales +ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 + +COPY --chown=rabbitmq:rabbitmq 10-defaults.conf 20-management_agent.disable_metrics_collector.conf /etc/rabbitmq/conf.d/ +COPY docker-entrypoint.sh /usr/local/bin/ +ENTRYPOINT ["docker-entrypoint.sh"] + +EXPOSE 4369 5671 5672 15691 15692 25672 +CMD ["rabbitmq-server"] diff --git a/4.1/alpine/docker-entrypoint.sh b/4.1/alpine/docker-entrypoint.sh new file mode 100755 index 00000000..7ecad434 --- /dev/null +++ b/4.1/alpine/docker-entrypoint.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +set -euo pipefail + +# allow the container to be started with `--user` +if [[ "$1" == rabbitmq* ]] && [ "$(id -u)" = '0' ]; then + if [ "$1" = 'rabbitmq-server' ]; then + find /var/lib/rabbitmq \! -user rabbitmq -exec chown rabbitmq '{}' + + fi + + exec su-exec rabbitmq "$BASH_SOURCE" "$@" +fi + +deprecatedEnvVars=( + RABBITMQ_DEFAULT_PASS_FILE + RABBITMQ_DEFAULT_USER_FILE + RABBITMQ_MANAGEMENT_SSL_CACERTFILE + RABBITMQ_MANAGEMENT_SSL_CERTFILE + RABBITMQ_MANAGEMENT_SSL_DEPTH + RABBITMQ_MANAGEMENT_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_MANAGEMENT_SSL_KEYFILE + RABBITMQ_MANAGEMENT_SSL_VERIFY + RABBITMQ_SSL_CACERTFILE + RABBITMQ_SSL_CERTFILE + RABBITMQ_SSL_DEPTH + RABBITMQ_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_SSL_KEYFILE + RABBITMQ_SSL_VERIFY + RABBITMQ_VM_MEMORY_HIGH_WATERMARK +) +hasOldEnv= +for old in "${deprecatedEnvVars[@]}"; do + if [ -n "${!old:-}" ]; then + echo >&2 "error: $old is set but deprecated" + hasOldEnv=1 + fi +done +if [ -n "$hasOldEnv" ]; then + echo >&2 'error: deprecated environment variables detected' + echo >&2 + echo >&2 'Please use a configuration file instead; visit https://www.rabbitmq.com/configure.html to learn more' + echo >&2 + exit 1 +fi + +# if long and short hostnames are not the same, use long hostnames +if [ -z "${RABBITMQ_USE_LONGNAME:-}" ] && [ "$(hostname)" != "$(hostname -s)" ]; then + : "${RABBITMQ_USE_LONGNAME:=true}" +fi + +exec "$@" diff --git a/4.1/alpine/management/Dockerfile b/4.1/alpine/management/Dockerfile new file mode 100644 index 00000000..c6954c42 --- /dev/null +++ b/4.1/alpine/management/Dockerfile @@ -0,0 +1,21 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +FROM rabbitmq:4.1-alpine + +RUN set -eux; \ + rabbitmq-plugins enable --offline rabbitmq_management; \ +# make sure the metrics collector is re-enabled (disabled in the base image for Prometheus-style metrics by default) + rm -f /etc/rabbitmq/conf.d/20-management_agent.disable_metrics_collector.conf; \ +# grab "rabbitmqadmin" from inside the "rabbitmq_management-X.Y.Z" plugin folder +# see https://github.com/docker-library/rabbitmq/issues/207 + cp /plugins/rabbitmq_management-*/priv/www/cli/rabbitmqadmin /usr/local/bin/rabbitmqadmin; \ + [ -s /usr/local/bin/rabbitmqadmin ]; \ + chmod +x /usr/local/bin/rabbitmqadmin; \ + apk add --no-cache python3; \ + rabbitmqadmin --version + +EXPOSE 15671 15672 diff --git a/4.1/ubuntu/10-defaults.conf b/4.1/ubuntu/10-defaults.conf new file mode 100644 index 00000000..27973c74 --- /dev/null +++ b/4.1/ubuntu/10-defaults.conf @@ -0,0 +1,12 @@ +## DEFAULT SETTINGS ARE NOT MEANT TO BE TAKEN STRAIGHT INTO PRODUCTION +## see https://www.rabbitmq.com/configure.html for further information +## on configuring RabbitMQ + +## allow access to the guest user from anywhere on the network +## https://www.rabbitmq.com/access-control.html#loopback-users +## https://www.rabbitmq.com/production-checklist.html#users +loopback_users.guest = false + +## Send all logs to stdout/TTY. Necessary to see logs when running via +## a container +log.console = true diff --git a/4.1/ubuntu/20-management_agent.disable_metrics_collector.conf b/4.1/ubuntu/20-management_agent.disable_metrics_collector.conf new file mode 100644 index 00000000..6eb7a86c --- /dev/null +++ b/4.1/ubuntu/20-management_agent.disable_metrics_collector.conf @@ -0,0 +1,2 @@ +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +management_agent.disable_metrics_collector = true diff --git a/4.1/ubuntu/Dockerfile b/4.1/ubuntu/Dockerfile new file mode 100644 index 00000000..dfd64ae8 --- /dev/null +++ b/4.1/ubuntu/Dockerfile @@ -0,0 +1,319 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +# 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:24.04 as build-base + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + build-essential \ + ca-certificates \ + gnupg \ + libncurses5-dev \ + wget + +FROM build-base as openssl-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +# Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally +ARG PGP_KEYSERVER=keyserver.ubuntu.com +# If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, +# run the build with a different PGP_KEYSERVER, e.g. docker build --tag rabbitmq:4.1 --build-arg PGP_KEYSERVER=pgpkeys.eu 4.1/ubuntu +# For context, see https://github.com/docker-library/official-images/issues/4252 + +ENV OPENSSL_VERSION 3.3.5 +ENV OPENSSL_SOURCE_SHA256="9d62c00a5a6903740c8703f0e006257f429d565d3b91ac1a9bd4a4c700002e01" +# https://www.openssl.org/source/ +ENV OPENSSL_PGP_KEY_IDS="0xBA5473A2B0587B07FB27CF2D216094DFD0CB81EF" + +ENV OTP_VERSION 27.3.4.3 +# TODO add PGP checking when the feature will be added to Erlang/OTP's build system +# https://erlang.org/pipermail/erlang-questions/2019-January/097067.html +ENV OTP_SOURCE_SHA256="597618c75890e8e606033bc8dbf6ec87fdf4e892c10b4912ae3c9a4f01384579" + +# install openssl & erlang to a path that isn't auto-checked for libs to prevent accidental use by system packages +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl + +# Install dependencies required to build Erlang/OTP from source +# https://erlang.org/doc/installation_guide/INSTALL.html +# dpkg-dev: Required to set up host & build type when compiling Erlang/OTP +# 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; \ + OPENSSL_SOURCE_URL="https://github.com/openssl/openssl/releases/download/openssl-$OPENSSL_VERSION/openssl-$OPENSSL_VERSION.tar.gz"; \ + OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ + OPENSSL_CONFIG_DIR="$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# Required by the crypto & ssl Erlang/OTP applications + wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_SOURCE_URL.asc"; \ + wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz" "$OPENSSL_SOURCE_URL"; \ + export GNUPGHOME="$(mktemp -d)"; \ + for key in $OPENSSL_PGP_KEY_IDS; do \ + gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \ + done; \ + gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum --check --strict -; \ + mkdir -p "$OPENSSL_PATH"; \ + tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \ + \ +# Configure OpenSSL for compilation + cd "$OPENSSL_PATH"; \ +# without specifying "--libdir", Erlang will fail during "crypto:supports()" looking for a "pthread_atfork" function that doesn't exist (but only on arm32v7/armhf??) +# OpenSSL's "config" script uses a lot of "uname"-based target detection... + dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ +# https://deb.debian.org/debian/dists/unstable/main/ + case "$dpkgArch" in \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L860 (look for "linux-" and "linux64-" keys) + amd64) opensslMachine='linux-x86_64' ;; \ + arm64) opensslMachine='linux-aarch64' ;; \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L736-L766 +# https://wiki.debian.org/ArchitectureSpecificsMemo#Architecture_baselines +# https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html + armhf) opensslMachine='linux-armv4'; opensslExtraConfig='-march=armv7-a+fp' ;; \ + i386) opensslMachine='linux-x86' ;; \ + ppc64el) opensslMachine='linux-ppc64le' ;; \ + riscv64) opensslMachine='linux64-riscv64' ;; \ + s390x) opensslMachine='linux64-s390x' ;; \ + *) echo >&2 "error: unsupported arch: '$apkArch'"; exit 1 ;; \ + esac; \ + MACHINE="$opensslMachine" \ + RELEASE="4.x.y-z" \ + SYSTEM='Linux' \ + BUILD='???' \ + ./Configure \ + "$opensslMachine" \ + enable-fips \ + --prefix="$OPENSSL_INSTALL_PATH_PREFIX" \ + --openssldir="$OPENSSL_CONFIG_DIR" \ + --libdir="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ +# 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) + -Wl,-rpath="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ + ${opensslExtraConfig:-} \ + ; \ +# Compile, install OpenSSL, verify that the command-line works & development headers are present + make -j "$(getconf _NPROCESSORS_ONLN)"; \ + make install_sw install_ssldirs install_fips; \ + 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" + +# smoke test +RUN $OPENSSL_INSTALL_PATH_PREFIX/bin/openssl version + +FROM openssl-builder as erlang-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +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"; \ + \ +# Download, verify & extract OTP_SOURCE + mkdir -p "$OTP_PATH"; \ + wget --progress dot:giga --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \ + echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum --check --strict -; \ + tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \ + \ +# Configure Erlang/OTP for compilation, disable unused features & applications +# https://erlang.org/doc/applications.html +# ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation + cd "$OTP_PATH"; \ + export ERL_TOP="$OTP_PATH"; \ + 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 "$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) + export CFLAGS="$CFLAGS -Wl,-rpath=$OPENSSL_INSTALL_PATH_PREFIX/lib"; \ + hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ + buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ + dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ +# JIT is only supported on amd64 + arm64; https://github.com/erlang/otp/blob/OTP-25.3.2.2/erts/configure#L24306-L24347 + jitFlag=; \ + case "$dpkgArch" in \ + amd64 | arm64) jitFlag='--enable-jit' ;; \ + esac; \ + ./configure \ + --prefix="$ERLANG_INSTALL_PATH_PREFIX" \ + --host="$hostArch" \ + --build="$buildArch" \ + --disable-hipe \ + --disable-sctp \ + --disable-silent-rules \ + --enable-builtin-zlib \ + --enable-clock-gettime \ + --enable-hybrid-heap \ + --enable-kernel-poll \ + --enable-smp-support \ + --enable-threads \ + --with-microstate-accounting=extra \ + --with-ssl="$OPENSSL_INSTALL_PATH_PREFIX" \ + --without-common_test \ + --without-debugger \ + --without-dialyzer \ + --without-diameter \ + --without-edoc \ + --without-erl_docgen \ + --without-et \ + --without-eunit \ + --without-ftp \ + --without-hipe \ + --without-jinterface \ + --without-megaco \ + --without-observer \ + --without-odbc \ + --without-reltool \ + --without-snmp \ + --without-ssh \ + --without-tftp \ + --without-wx \ + $jitFlag \ + ; \ + \ +# Compile & install Erlang/OTP + make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ + make install; \ + \ +# Remove unnecessary files + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name examples -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name src -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name include -exec rm -rf '{}' + + +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$PATH +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 }' +RUN erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' + +FROM ubuntu:24.04 + +# OPENSSL/ERLANG_INSTALL_PATH_PREFIX are defined in a different stage, so define them again +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl +COPY --from=erlang-builder $ERLANG_INSTALL_PATH_PREFIX $ERLANG_INSTALL_PATH_PREFIX +COPY --from=openssl-builder $OPENSSL_INSTALL_PATH_PREFIX $OPENSSL_INSTALL_PATH_PREFIX + +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$OPENSSL_INSTALL_PATH_PREFIX/bin:$PATH + +ENV RABBITMQ_DATA_DIR /var/lib/rabbitmq + +RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# Check that OpenSSL still works after copying from previous builder + ldconfig; \ + sed -i.ORIG -e "/\.include.*fips/ s!.*!.include $OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf!" \ + -e '/# fips =/s/.*/fips = fips_sect/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/openssl.cnf"; \ + sed -i.ORIG -e '/^activate/s/^/#/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf"; \ + [ "$(command -v openssl)" = "$OPENSSL_INSTALL_PATH_PREFIX/bin/openssl" ]; \ + openssl version; \ + openssl version -d; \ + \ +# 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; \ + chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ + chmod 1777 "$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 + +# Use the latest stable RabbitMQ release (https://www.rabbitmq.com/download.html) +ENV RABBITMQ_VERSION 4.1.4 +# https://www.rabbitmq.com/signatures.html#importing-gpg +ENV RABBITMQ_PGP_KEY_ID 0x0A9AF2115F4687BD29803A206B73A36E6026DFCA +ENV RABBITMQ_HOME /opt/rabbitmq + +# Add RabbitMQ to PATH +ENV PATH $RABBITMQ_HOME/sbin:$PATH + +# Install RabbitMQ +RUN set -eux; \ + 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 \ + ; \ + rm -rf /var/lib/apt/lists/*; \ + \ + RABBITMQ_SOURCE_URL="https://github.com/rabbitmq/rabbitmq-server/releases/download/v$RABBITMQ_VERSION/rabbitmq-server-generic-unix-latest-toolchain-$RABBITMQ_VERSION.tar.xz"; \ + RABBITMQ_PATH="/usr/local/src/rabbitmq-$RABBITMQ_VERSION"; \ + \ + wget --progress dot:giga --output-document "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_SOURCE_URL.asc"; \ + wget --progress dot:giga --output-document "$RABBITMQ_PATH.tar.xz" "$RABBITMQ_SOURCE_URL"; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$RABBITMQ_PGP_KEY_ID"; \ + gpg --batch --verify "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_PATH.tar.xz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + \ + mkdir -p "$RABBITMQ_HOME"; \ + tar --extract --file "$RABBITMQ_PATH.tar.xz" --directory "$RABBITMQ_HOME" --strip-components 1; \ + rm -rf "$RABBITMQ_PATH"*; \ +# Do not default SYS_PREFIX to RABBITMQ_HOME, leave it empty + grep -qE '^SYS_PREFIX=\$\{RABBITMQ_HOME\}$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + sed -i 's/^SYS_PREFIX=.*$/SYS_PREFIX=/' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ + \ + apt-mark auto '.*' > /dev/null; \ + apt-mark manual $savedAptMark; \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + \ +# verify assumption of no stale cookies + [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ +# Ensure RabbitMQ was installed correctly by running a few commands that do not depend on a running server, as the rabbitmq user +# If they all succeed, it's safe to assume that things have been set up correctly + gosu rabbitmq rabbitmqctl help; \ + gosu rabbitmq rabbitmqctl list_ciphers; \ + gosu rabbitmq rabbitmq-plugins list; \ +# no stale cookies + rm "$RABBITMQ_DATA_DIR/.erlang.cookie" + +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +RUN gosu rabbitmq rabbitmq-plugins enable --offline rabbitmq_prometheus + +# Added for backwards compatibility - users can simply COPY custom plugins to /plugins +RUN ln -sf /opt/rabbitmq/plugins /plugins + +# set home so that any `--user` knows where to put the erlang cookie +ENV HOME $RABBITMQ_DATA_DIR +# Hint that the data (a.k.a. home dir) dir should be separate volume +VOLUME $RABBITMQ_DATA_DIR + +# warning: the VM is running with native name encoding of latin1 which may cause Elixir to malfunction as it expects utf8. Please ensure your locale is set to UTF-8 (which can be verified by running "locale" in your shell) +# Setting all environment variables that control language preferences, behaviour differs - https://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html#The-LANGUAGE-variable +# https://docs.docker.com/samples/library/ubuntu/#locales +ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 + +COPY --chown=rabbitmq:rabbitmq 10-defaults.conf 20-management_agent.disable_metrics_collector.conf /etc/rabbitmq/conf.d/ +COPY docker-entrypoint.sh /usr/local/bin/ +ENTRYPOINT ["docker-entrypoint.sh"] + +EXPOSE 4369 5671 5672 15691 15692 25672 +CMD ["rabbitmq-server"] diff --git a/4.1/ubuntu/docker-entrypoint.sh b/4.1/ubuntu/docker-entrypoint.sh new file mode 100755 index 00000000..c1c55b6d --- /dev/null +++ b/4.1/ubuntu/docker-entrypoint.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +set -euo pipefail + +# allow the container to be started with `--user` +if [[ "$1" == rabbitmq* ]] && [ "$(id -u)" = '0' ]; then + if [ "$1" = 'rabbitmq-server' ]; then + find /var/lib/rabbitmq \! -user rabbitmq -exec chown rabbitmq '{}' + + fi + + exec gosu rabbitmq "$BASH_SOURCE" "$@" +fi + +deprecatedEnvVars=( + RABBITMQ_DEFAULT_PASS_FILE + RABBITMQ_DEFAULT_USER_FILE + RABBITMQ_MANAGEMENT_SSL_CACERTFILE + RABBITMQ_MANAGEMENT_SSL_CERTFILE + RABBITMQ_MANAGEMENT_SSL_DEPTH + RABBITMQ_MANAGEMENT_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_MANAGEMENT_SSL_KEYFILE + RABBITMQ_MANAGEMENT_SSL_VERIFY + RABBITMQ_SSL_CACERTFILE + RABBITMQ_SSL_CERTFILE + RABBITMQ_SSL_DEPTH + RABBITMQ_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_SSL_KEYFILE + RABBITMQ_SSL_VERIFY + RABBITMQ_VM_MEMORY_HIGH_WATERMARK +) +hasOldEnv= +for old in "${deprecatedEnvVars[@]}"; do + if [ -n "${!old:-}" ]; then + echo >&2 "error: $old is set but deprecated" + hasOldEnv=1 + fi +done +if [ -n "$hasOldEnv" ]; then + echo >&2 'error: deprecated environment variables detected' + echo >&2 + echo >&2 'Please use a configuration file instead; visit https://www.rabbitmq.com/configure.html to learn more' + echo >&2 + exit 1 +fi + +# if long and short hostnames are not the same, use long hostnames +if [ -z "${RABBITMQ_USE_LONGNAME:-}" ] && [ "$(hostname)" != "$(hostname -s)" ]; then + : "${RABBITMQ_USE_LONGNAME:=true}" +fi + +exec "$@" diff --git a/4.1/ubuntu/management/Dockerfile b/4.1/ubuntu/management/Dockerfile new file mode 100644 index 00000000..ab511bf6 --- /dev/null +++ b/4.1/ubuntu/management/Dockerfile @@ -0,0 +1,23 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +FROM rabbitmq:4.1 + +RUN set -eux; \ + rabbitmq-plugins enable --offline rabbitmq_management; \ +# make sure the metrics collector is re-enabled (disabled in the base image for Prometheus-style metrics by default) + rm -f /etc/rabbitmq/conf.d/20-management_agent.disable_metrics_collector.conf; \ +# grab "rabbitmqadmin" from inside the "rabbitmq_management-X.Y.Z" plugin folder +# see https://github.com/docker-library/rabbitmq/issues/207 + cp /plugins/rabbitmq_management-*/priv/www/cli/rabbitmqadmin /usr/local/bin/rabbitmqadmin; \ + [ -s /usr/local/bin/rabbitmqadmin ]; \ + chmod +x /usr/local/bin/rabbitmqadmin; \ + apt-get update; \ + apt-get install -y --no-install-recommends python3; \ + rm -rf /var/lib/apt/lists/*; \ + rabbitmqadmin --version + +EXPOSE 15671 15672 diff --git a/4.2-rc/alpine/10-defaults.conf b/4.2-rc/alpine/10-defaults.conf new file mode 100644 index 00000000..27973c74 --- /dev/null +++ b/4.2-rc/alpine/10-defaults.conf @@ -0,0 +1,12 @@ +## DEFAULT SETTINGS ARE NOT MEANT TO BE TAKEN STRAIGHT INTO PRODUCTION +## see https://www.rabbitmq.com/configure.html for further information +## on configuring RabbitMQ + +## allow access to the guest user from anywhere on the network +## https://www.rabbitmq.com/access-control.html#loopback-users +## https://www.rabbitmq.com/production-checklist.html#users +loopback_users.guest = false + +## Send all logs to stdout/TTY. Necessary to see logs when running via +## a container +log.console = true diff --git a/4.2-rc/alpine/20-management_agent.disable_metrics_collector.conf b/4.2-rc/alpine/20-management_agent.disable_metrics_collector.conf new file mode 100644 index 00000000..6eb7a86c --- /dev/null +++ b/4.2-rc/alpine/20-management_agent.disable_metrics_collector.conf @@ -0,0 +1,2 @@ +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +management_agent.disable_metrics_collector = true diff --git a/4.2-rc/alpine/Dockerfile b/4.2-rc/alpine/Dockerfile new file mode 100644 index 00000000..8b965f71 --- /dev/null +++ b/4.2-rc/alpine/Dockerfile @@ -0,0 +1,325 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +# Alpine Linux is not officially supported by the RabbitMQ team -- use at your own risk! +FROM alpine:3.22 as build-base + +RUN apk add --no-cache \ + build-base \ + dpkg-dev \ + dpkg \ + gnupg \ + libc-dev \ + linux-headers \ + ncurses-dev + +FROM build-base as openssl-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +# Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally +ARG PGP_KEYSERVER=keyserver.ubuntu.com +# If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, +# run the build with a different PGP_KEYSERVER, e.g. docker build --tag rabbitmq:4.2-rc --build-arg PGP_KEYSERVER=pgpkeys.eu 4.2-rc/ubuntu +# For context, see https://github.com/docker-library/official-images/issues/4252 + +ENV OPENSSL_VERSION 3.3.5 +ENV OPENSSL_SOURCE_SHA256="9d62c00a5a6903740c8703f0e006257f429d565d3b91ac1a9bd4a4c700002e01" +# https://www.openssl.org/source/ +ENV OPENSSL_PGP_KEY_IDS="0xBA5473A2B0587B07FB27CF2D216094DFD0CB81EF" + +ENV OTP_VERSION 27.3.4.3 +# TODO add PGP checking when the feature will be added to Erlang/OTP's build system +# https://erlang.org/pipermail/erlang-questions/2019-January/097067.html +ENV OTP_SOURCE_SHA256="597618c75890e8e606033bc8dbf6ec87fdf4e892c10b4912ae3c9a4f01384579" + +# install openssl & erlang to a path that isn't auto-checked for libs to prevent accidental use by system packages +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl + +# Install dependencies required to build Erlang/OTP from source +# https://erlang.org/doc/installation_guide/INSTALL.html +# dpkg-dev: Required to set up host & build type when compiling Erlang/OTP +# 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; \ +# /usr/local/src doesn't exist in Alpine by default + mkdir -p /usr/local/src; \ + \ + OPENSSL_SOURCE_URL="https://github.com/openssl/openssl/releases/download/openssl-$OPENSSL_VERSION/openssl-$OPENSSL_VERSION.tar.gz"; \ + OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ + OPENSSL_CONFIG_DIR="$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# 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"; \ + export GNUPGHOME="$(mktemp -d)"; \ + for key in $OPENSSL_PGP_KEY_IDS; do \ + gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \ + done; \ + gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum -c -; \ + mkdir -p "$OPENSSL_PATH"; \ + tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \ + \ +# Configure OpenSSL for compilation + cd "$OPENSSL_PATH"; \ +# OpenSSL's "config" script uses a lot of "uname"-based target detection... + apkArch="$(apk --print-arch)"; \ +# https://dl-cdn.alpinelinux.org/alpine/edge/main/ + case "$apkArch" in \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L860 (look for "linux-" and "linux64-" keys) + aarch64) opensslMachine='linux-aarch64' ;; \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L736-L766 +# https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html + armhf) opensslMachine='linux-armv4'; opensslExtraConfig='-march=armv6+fp' ;; \ + armv7) opensslMachine='linux-armv4'; opensslExtraConfig='-march=armv7-a+fp' ;; \ + ppc64le) opensslMachine='linux-ppc64le' ;; \ + riscv64) opensslMachine='linux64-riscv64' ;; \ + s390x) opensslMachine='linux64-s390x' ;; \ + x86) opensslMachine='linux-x86' ;; \ + x86_64) opensslMachine='linux-x86_64' ;; \ + *) echo >&2 "error: unsupported arch: '$apkArch'"; exit 1 ;; \ + esac; \ + MACHINE="$opensslMachine" \ + RELEASE="4.x.y-z" \ + SYSTEM='Linux' \ + BUILD='???' \ + ./Configure \ + "$opensslMachine" \ + enable-fips \ + --prefix="$OPENSSL_INSTALL_PATH_PREFIX" \ + --openssldir="$OPENSSL_CONFIG_DIR" \ + --libdir="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ +# 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) + -Wl,-rpath="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ + ${opensslExtraConfig:-} \ + ; \ +# Compile, install OpenSSL, verify that the command-line works & development headers are present + make -j "$(getconf _NPROCESSORS_ONLN)"; \ + make install_sw install_ssldirs install_fips; \ +# 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" + +# smoke test +RUN $OPENSSL_INSTALL_PATH_PREFIX/bin/openssl version + +FROM openssl-builder as erlang-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +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"; \ + \ +# Download, verify & extract OTP_SOURCE + mkdir -p "$OTP_PATH"; \ + wget --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \ + echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum -c -; \ + tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \ + \ +# Configure Erlang/OTP for compilation, disable unused features & applications +# https://erlang.org/doc/applications.html +# ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation + cd "$OTP_PATH"; \ + export ERL_TOP="$OTP_PATH"; \ + export CFLAGS='-g -O2'; \ +# 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) + export CFLAGS="$CFLAGS -Wl,-rpath=$OPENSSL_INSTALL_PATH_PREFIX/lib"; \ + hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ + buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ + dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ +# JIT is only supported on amd64 + arm64; https://github.com/erlang/otp/blob/OTP-25.3.2.2/erts/configure#L24306-L24347 + jitFlag=; \ + case "$dpkgArch" in \ + amd64 | arm64) jitFlag='--enable-jit' ;; \ + esac; \ + ./configure \ + --prefix="$ERLANG_INSTALL_PATH_PREFIX" \ + --host="$hostArch" \ + --build="$buildArch" \ + --disable-hipe \ + --disable-sctp \ + --disable-silent-rules \ + --enable-builtin-zlib \ + --enable-clock-gettime \ + --enable-hybrid-heap \ + --enable-kernel-poll \ + --enable-smp-support \ + --enable-threads \ + --with-microstate-accounting=extra \ + --with-ssl="$OPENSSL_INSTALL_PATH_PREFIX" \ + --without-common_test \ + --without-debugger \ + --without-dialyzer \ + --without-diameter \ + --without-edoc \ + --without-erl_docgen \ + --without-et \ + --without-eunit \ + --without-ftp \ + --without-hipe \ + --without-jinterface \ + --without-megaco \ + --without-observer \ + --without-odbc \ + --without-reltool \ + --without-snmp \ + --without-ssh \ + --without-tftp \ + --without-wx \ + $jitFlag \ + ; \ +# Compile & install Erlang/OTP + make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ + make install; \ + \ +# Remove unnecessary files + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name examples -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name src -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name include -exec rm -rf '{}' + + +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$PATH +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 }' +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.22 + +# OPENSSL/ERLANG_INSTALL_PATH_PREFIX are defined in a different stage, so define them again +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl + +COPY --from=erlang-builder $ERLANG_INSTALL_PATH_PREFIX $ERLANG_INSTALL_PATH_PREFIX +COPY --from=openssl-builder $OPENSSL_INSTALL_PATH_PREFIX $OPENSSL_INSTALL_PATH_PREFIX + +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$OPENSSL_INSTALL_PATH_PREFIX/bin:$PATH + +ENV RABBITMQ_DATA_DIR /var/lib/rabbitmq + +RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# Ensure run-time dependencies are installed + runDeps="$( \ + scanelf --needed --nobanner --format '%n#p' --recursive $ERLANG_INSTALL_PATH_PREFIX $OPENSSL_INSTALL_PATH_PREFIX \ + | tr ',' '\n' \ + | sort -u \ + | grep -v '^$\|lib\(crypto\|ssl\)' \ + | awk 'system("test -e /usr/local/lib/" $1) == 0 { next } { print "so:" $1 }' \ + )"; \ + apk add --no-cache --virtual .otp-run-deps $runDeps; \ + \ +# Check that OpenSSL still works after copying from previous builder + sed -i.ORIG -e "/\.include.*fips/ s!.*!.include $OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf!" \ + -e '/# fips =/s/.*/fips = fips_sect/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/openssl.cnf"; \ + sed -i.ORIG -e '/^activate/s/^/#/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf"; \ + [ "$(command -v openssl)" = "$OPENSSL_INSTALL_PATH_PREFIX/bin/openssl" ]; \ + openssl version; \ + openssl version -d; \ + \ +# 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 + 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 1777 "$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; \ + \ + 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 4.2.0-beta.4 +# https://www.rabbitmq.com/signatures.html#importing-gpg +ENV RABBITMQ_PGP_KEY_ID 0x0A9AF2115F4687BD29803A206B73A36E6026DFCA +ENV RABBITMQ_HOME /opt/rabbitmq + +# Add RabbitMQ to PATH +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 \ + xz \ + ; \ + \ + RABBITMQ_SOURCE_URL="https://github.com/rabbitmq/rabbitmq-server/releases/download/v$RABBITMQ_VERSION/rabbitmq-server-generic-unix-latest-toolchain-$RABBITMQ_VERSION.tar.xz"; \ + RABBITMQ_PATH="/usr/local/src/rabbitmq-$RABBITMQ_VERSION"; \ + \ + wget --output-document "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_SOURCE_URL.asc"; \ + wget --output-document "$RABBITMQ_PATH.tar.xz" "$RABBITMQ_SOURCE_URL"; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$RABBITMQ_PGP_KEY_ID"; \ + gpg --batch --verify "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_PATH.tar.xz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + \ + mkdir -p "$RABBITMQ_HOME"; \ + tar --extract --file "$RABBITMQ_PATH.tar.xz" --directory "$RABBITMQ_HOME" --strip-components 1; \ + rm -rf "$RABBITMQ_PATH"*; \ +# Do not default SYS_PREFIX to RABBITMQ_HOME, leave it empty + grep -qE '^SYS_PREFIX=\$\{RABBITMQ_HOME\}$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + sed -i 's/^SYS_PREFIX=.*$/SYS_PREFIX=/' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ + \ + apk del --no-network .build-deps; \ + \ +# verify assumption of no stale cookies + [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ +# Ensure RabbitMQ was installed correctly by running a few commands that do not depend on a running server, as the rabbitmq user +# If they all succeed, it's safe to assume that things have been set up correctly + su-exec rabbitmq rabbitmqctl help; \ + su-exec rabbitmq rabbitmqctl list_ciphers; \ + su-exec rabbitmq rabbitmq-plugins list; \ +# no stale cookies + rm "$RABBITMQ_DATA_DIR/.erlang.cookie" + +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +RUN su-exec rabbitmq rabbitmq-plugins enable --offline rabbitmq_prometheus + +# Added for backwards compatibility - users can simply COPY custom plugins to /plugins +RUN ln -sf /opt/rabbitmq/plugins /plugins + +# set home so that any `--user` knows where to put the erlang cookie +ENV HOME $RABBITMQ_DATA_DIR +# Hint that the data (a.k.a. home dir) dir should be separate volume +VOLUME $RABBITMQ_DATA_DIR + +# warning: the VM is running with native name encoding of latin1 which may cause Elixir to malfunction as it expects utf8. Please ensure your locale is set to UTF-8 (which can be verified by running "locale" in your shell) +# Setting all environment variables that control language preferences, behaviour differs - https://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html#The-LANGUAGE-variable +# https://docs.docker.com/samples/library/ubuntu/#locales +ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 + +COPY --chown=rabbitmq:rabbitmq 10-defaults.conf 20-management_agent.disable_metrics_collector.conf /etc/rabbitmq/conf.d/ +COPY docker-entrypoint.sh /usr/local/bin/ +ENTRYPOINT ["docker-entrypoint.sh"] + +EXPOSE 4369 5671 5672 15691 15692 25672 +CMD ["rabbitmq-server"] diff --git a/4.2-rc/alpine/docker-entrypoint.sh b/4.2-rc/alpine/docker-entrypoint.sh new file mode 100755 index 00000000..7ecad434 --- /dev/null +++ b/4.2-rc/alpine/docker-entrypoint.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +set -euo pipefail + +# allow the container to be started with `--user` +if [[ "$1" == rabbitmq* ]] && [ "$(id -u)" = '0' ]; then + if [ "$1" = 'rabbitmq-server' ]; then + find /var/lib/rabbitmq \! -user rabbitmq -exec chown rabbitmq '{}' + + fi + + exec su-exec rabbitmq "$BASH_SOURCE" "$@" +fi + +deprecatedEnvVars=( + RABBITMQ_DEFAULT_PASS_FILE + RABBITMQ_DEFAULT_USER_FILE + RABBITMQ_MANAGEMENT_SSL_CACERTFILE + RABBITMQ_MANAGEMENT_SSL_CERTFILE + RABBITMQ_MANAGEMENT_SSL_DEPTH + RABBITMQ_MANAGEMENT_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_MANAGEMENT_SSL_KEYFILE + RABBITMQ_MANAGEMENT_SSL_VERIFY + RABBITMQ_SSL_CACERTFILE + RABBITMQ_SSL_CERTFILE + RABBITMQ_SSL_DEPTH + RABBITMQ_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_SSL_KEYFILE + RABBITMQ_SSL_VERIFY + RABBITMQ_VM_MEMORY_HIGH_WATERMARK +) +hasOldEnv= +for old in "${deprecatedEnvVars[@]}"; do + if [ -n "${!old:-}" ]; then + echo >&2 "error: $old is set but deprecated" + hasOldEnv=1 + fi +done +if [ -n "$hasOldEnv" ]; then + echo >&2 'error: deprecated environment variables detected' + echo >&2 + echo >&2 'Please use a configuration file instead; visit https://www.rabbitmq.com/configure.html to learn more' + echo >&2 + exit 1 +fi + +# if long and short hostnames are not the same, use long hostnames +if [ -z "${RABBITMQ_USE_LONGNAME:-}" ] && [ "$(hostname)" != "$(hostname -s)" ]; then + : "${RABBITMQ_USE_LONGNAME:=true}" +fi + +exec "$@" diff --git a/4.2-rc/alpine/management/Dockerfile b/4.2-rc/alpine/management/Dockerfile new file mode 100644 index 00000000..9e92954a --- /dev/null +++ b/4.2-rc/alpine/management/Dockerfile @@ -0,0 +1,21 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +FROM rabbitmq:4.2-rc-alpine + +RUN set -eux; \ + rabbitmq-plugins enable --offline rabbitmq_management; \ +# make sure the metrics collector is re-enabled (disabled in the base image for Prometheus-style metrics by default) + rm -f /etc/rabbitmq/conf.d/20-management_agent.disable_metrics_collector.conf; \ +# grab "rabbitmqadmin" from inside the "rabbitmq_management-X.Y.Z" plugin folder +# see https://github.com/docker-library/rabbitmq/issues/207 + cp /plugins/rabbitmq_management-*/priv/www/cli/rabbitmqadmin /usr/local/bin/rabbitmqadmin; \ + [ -s /usr/local/bin/rabbitmqadmin ]; \ + chmod +x /usr/local/bin/rabbitmqadmin; \ + apk add --no-cache python3; \ + rabbitmqadmin --version + +EXPOSE 15671 15672 diff --git a/4.2-rc/ubuntu/10-defaults.conf b/4.2-rc/ubuntu/10-defaults.conf new file mode 100644 index 00000000..27973c74 --- /dev/null +++ b/4.2-rc/ubuntu/10-defaults.conf @@ -0,0 +1,12 @@ +## DEFAULT SETTINGS ARE NOT MEANT TO BE TAKEN STRAIGHT INTO PRODUCTION +## see https://www.rabbitmq.com/configure.html for further information +## on configuring RabbitMQ + +## allow access to the guest user from anywhere on the network +## https://www.rabbitmq.com/access-control.html#loopback-users +## https://www.rabbitmq.com/production-checklist.html#users +loopback_users.guest = false + +## Send all logs to stdout/TTY. Necessary to see logs when running via +## a container +log.console = true diff --git a/4.2-rc/ubuntu/20-management_agent.disable_metrics_collector.conf b/4.2-rc/ubuntu/20-management_agent.disable_metrics_collector.conf new file mode 100644 index 00000000..6eb7a86c --- /dev/null +++ b/4.2-rc/ubuntu/20-management_agent.disable_metrics_collector.conf @@ -0,0 +1,2 @@ +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +management_agent.disable_metrics_collector = true diff --git a/4.2-rc/ubuntu/Dockerfile b/4.2-rc/ubuntu/Dockerfile new file mode 100644 index 00000000..fe09b98f --- /dev/null +++ b/4.2-rc/ubuntu/Dockerfile @@ -0,0 +1,319 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +# 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:24.04 as build-base + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + build-essential \ + ca-certificates \ + gnupg \ + libncurses5-dev \ + wget + +FROM build-base as openssl-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +# Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally +ARG PGP_KEYSERVER=keyserver.ubuntu.com +# If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, +# run the build with a different PGP_KEYSERVER, e.g. docker build --tag rabbitmq:4.2-rc --build-arg PGP_KEYSERVER=pgpkeys.eu 4.2-rc/ubuntu +# For context, see https://github.com/docker-library/official-images/issues/4252 + +ENV OPENSSL_VERSION 3.3.5 +ENV OPENSSL_SOURCE_SHA256="9d62c00a5a6903740c8703f0e006257f429d565d3b91ac1a9bd4a4c700002e01" +# https://www.openssl.org/source/ +ENV OPENSSL_PGP_KEY_IDS="0xBA5473A2B0587B07FB27CF2D216094DFD0CB81EF" + +ENV OTP_VERSION 27.3.4.3 +# TODO add PGP checking when the feature will be added to Erlang/OTP's build system +# https://erlang.org/pipermail/erlang-questions/2019-January/097067.html +ENV OTP_SOURCE_SHA256="597618c75890e8e606033bc8dbf6ec87fdf4e892c10b4912ae3c9a4f01384579" + +# install openssl & erlang to a path that isn't auto-checked for libs to prevent accidental use by system packages +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl + +# Install dependencies required to build Erlang/OTP from source +# https://erlang.org/doc/installation_guide/INSTALL.html +# dpkg-dev: Required to set up host & build type when compiling Erlang/OTP +# 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; \ + OPENSSL_SOURCE_URL="https://github.com/openssl/openssl/releases/download/openssl-$OPENSSL_VERSION/openssl-$OPENSSL_VERSION.tar.gz"; \ + OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ + OPENSSL_CONFIG_DIR="$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# Required by the crypto & ssl Erlang/OTP applications + wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_SOURCE_URL.asc"; \ + wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz" "$OPENSSL_SOURCE_URL"; \ + export GNUPGHOME="$(mktemp -d)"; \ + for key in $OPENSSL_PGP_KEY_IDS; do \ + gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \ + done; \ + gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum --check --strict -; \ + mkdir -p "$OPENSSL_PATH"; \ + tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \ + \ +# Configure OpenSSL for compilation + cd "$OPENSSL_PATH"; \ +# without specifying "--libdir", Erlang will fail during "crypto:supports()" looking for a "pthread_atfork" function that doesn't exist (but only on arm32v7/armhf??) +# OpenSSL's "config" script uses a lot of "uname"-based target detection... + dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ +# https://deb.debian.org/debian/dists/unstable/main/ + case "$dpkgArch" in \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L860 (look for "linux-" and "linux64-" keys) + amd64) opensslMachine='linux-x86_64' ;; \ + arm64) opensslMachine='linux-aarch64' ;; \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L736-L766 +# https://wiki.debian.org/ArchitectureSpecificsMemo#Architecture_baselines +# https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html + armhf) opensslMachine='linux-armv4'; opensslExtraConfig='-march=armv7-a+fp' ;; \ + i386) opensslMachine='linux-x86' ;; \ + ppc64el) opensslMachine='linux-ppc64le' ;; \ + riscv64) opensslMachine='linux64-riscv64' ;; \ + s390x) opensslMachine='linux64-s390x' ;; \ + *) echo >&2 "error: unsupported arch: '$apkArch'"; exit 1 ;; \ + esac; \ + MACHINE="$opensslMachine" \ + RELEASE="4.x.y-z" \ + SYSTEM='Linux' \ + BUILD='???' \ + ./Configure \ + "$opensslMachine" \ + enable-fips \ + --prefix="$OPENSSL_INSTALL_PATH_PREFIX" \ + --openssldir="$OPENSSL_CONFIG_DIR" \ + --libdir="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ +# 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) + -Wl,-rpath="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ + ${opensslExtraConfig:-} \ + ; \ +# Compile, install OpenSSL, verify that the command-line works & development headers are present + make -j "$(getconf _NPROCESSORS_ONLN)"; \ + make install_sw install_ssldirs install_fips; \ + 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" + +# smoke test +RUN $OPENSSL_INSTALL_PATH_PREFIX/bin/openssl version + +FROM openssl-builder as erlang-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +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"; \ + \ +# Download, verify & extract OTP_SOURCE + mkdir -p "$OTP_PATH"; \ + wget --progress dot:giga --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \ + echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum --check --strict -; \ + tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \ + \ +# Configure Erlang/OTP for compilation, disable unused features & applications +# https://erlang.org/doc/applications.html +# ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation + cd "$OTP_PATH"; \ + export ERL_TOP="$OTP_PATH"; \ + 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 "$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) + export CFLAGS="$CFLAGS -Wl,-rpath=$OPENSSL_INSTALL_PATH_PREFIX/lib"; \ + hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ + buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ + dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ +# JIT is only supported on amd64 + arm64; https://github.com/erlang/otp/blob/OTP-25.3.2.2/erts/configure#L24306-L24347 + jitFlag=; \ + case "$dpkgArch" in \ + amd64 | arm64) jitFlag='--enable-jit' ;; \ + esac; \ + ./configure \ + --prefix="$ERLANG_INSTALL_PATH_PREFIX" \ + --host="$hostArch" \ + --build="$buildArch" \ + --disable-hipe \ + --disable-sctp \ + --disable-silent-rules \ + --enable-builtin-zlib \ + --enable-clock-gettime \ + --enable-hybrid-heap \ + --enable-kernel-poll \ + --enable-smp-support \ + --enable-threads \ + --with-microstate-accounting=extra \ + --with-ssl="$OPENSSL_INSTALL_PATH_PREFIX" \ + --without-common_test \ + --without-debugger \ + --without-dialyzer \ + --without-diameter \ + --without-edoc \ + --without-erl_docgen \ + --without-et \ + --without-eunit \ + --without-ftp \ + --without-hipe \ + --without-jinterface \ + --without-megaco \ + --without-observer \ + --without-odbc \ + --without-reltool \ + --without-snmp \ + --without-ssh \ + --without-tftp \ + --without-wx \ + $jitFlag \ + ; \ + \ +# Compile & install Erlang/OTP + make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ + make install; \ + \ +# Remove unnecessary files + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name examples -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name src -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name include -exec rm -rf '{}' + + +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$PATH +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 }' +RUN erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' + +FROM ubuntu:24.04 + +# OPENSSL/ERLANG_INSTALL_PATH_PREFIX are defined in a different stage, so define them again +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl +COPY --from=erlang-builder $ERLANG_INSTALL_PATH_PREFIX $ERLANG_INSTALL_PATH_PREFIX +COPY --from=openssl-builder $OPENSSL_INSTALL_PATH_PREFIX $OPENSSL_INSTALL_PATH_PREFIX + +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$OPENSSL_INSTALL_PATH_PREFIX/bin:$PATH + +ENV RABBITMQ_DATA_DIR /var/lib/rabbitmq + +RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# Check that OpenSSL still works after copying from previous builder + ldconfig; \ + sed -i.ORIG -e "/\.include.*fips/ s!.*!.include $OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf!" \ + -e '/# fips =/s/.*/fips = fips_sect/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/openssl.cnf"; \ + sed -i.ORIG -e '/^activate/s/^/#/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf"; \ + [ "$(command -v openssl)" = "$OPENSSL_INSTALL_PATH_PREFIX/bin/openssl" ]; \ + openssl version; \ + openssl version -d; \ + \ +# 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; \ + chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ + chmod 1777 "$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 + +# Use the latest stable RabbitMQ release (https://www.rabbitmq.com/download.html) +ENV RABBITMQ_VERSION 4.2.0-beta.4 +# https://www.rabbitmq.com/signatures.html#importing-gpg +ENV RABBITMQ_PGP_KEY_ID 0x0A9AF2115F4687BD29803A206B73A36E6026DFCA +ENV RABBITMQ_HOME /opt/rabbitmq + +# Add RabbitMQ to PATH +ENV PATH $RABBITMQ_HOME/sbin:$PATH + +# Install RabbitMQ +RUN set -eux; \ + 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 \ + ; \ + rm -rf /var/lib/apt/lists/*; \ + \ + RABBITMQ_SOURCE_URL="https://github.com/rabbitmq/rabbitmq-server/releases/download/v$RABBITMQ_VERSION/rabbitmq-server-generic-unix-latest-toolchain-$RABBITMQ_VERSION.tar.xz"; \ + RABBITMQ_PATH="/usr/local/src/rabbitmq-$RABBITMQ_VERSION"; \ + \ + wget --progress dot:giga --output-document "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_SOURCE_URL.asc"; \ + wget --progress dot:giga --output-document "$RABBITMQ_PATH.tar.xz" "$RABBITMQ_SOURCE_URL"; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$RABBITMQ_PGP_KEY_ID"; \ + gpg --batch --verify "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_PATH.tar.xz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + \ + mkdir -p "$RABBITMQ_HOME"; \ + tar --extract --file "$RABBITMQ_PATH.tar.xz" --directory "$RABBITMQ_HOME" --strip-components 1; \ + rm -rf "$RABBITMQ_PATH"*; \ +# Do not default SYS_PREFIX to RABBITMQ_HOME, leave it empty + grep -qE '^SYS_PREFIX=\$\{RABBITMQ_HOME\}$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + sed -i 's/^SYS_PREFIX=.*$/SYS_PREFIX=/' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ + \ + apt-mark auto '.*' > /dev/null; \ + apt-mark manual $savedAptMark; \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + \ +# verify assumption of no stale cookies + [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ +# Ensure RabbitMQ was installed correctly by running a few commands that do not depend on a running server, as the rabbitmq user +# If they all succeed, it's safe to assume that things have been set up correctly + gosu rabbitmq rabbitmqctl help; \ + gosu rabbitmq rabbitmqctl list_ciphers; \ + gosu rabbitmq rabbitmq-plugins list; \ +# no stale cookies + rm "$RABBITMQ_DATA_DIR/.erlang.cookie" + +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +RUN gosu rabbitmq rabbitmq-plugins enable --offline rabbitmq_prometheus + +# Added for backwards compatibility - users can simply COPY custom plugins to /plugins +RUN ln -sf /opt/rabbitmq/plugins /plugins + +# set home so that any `--user` knows where to put the erlang cookie +ENV HOME $RABBITMQ_DATA_DIR +# Hint that the data (a.k.a. home dir) dir should be separate volume +VOLUME $RABBITMQ_DATA_DIR + +# warning: the VM is running with native name encoding of latin1 which may cause Elixir to malfunction as it expects utf8. Please ensure your locale is set to UTF-8 (which can be verified by running "locale" in your shell) +# Setting all environment variables that control language preferences, behaviour differs - https://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html#The-LANGUAGE-variable +# https://docs.docker.com/samples/library/ubuntu/#locales +ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 + +COPY --chown=rabbitmq:rabbitmq 10-defaults.conf 20-management_agent.disable_metrics_collector.conf /etc/rabbitmq/conf.d/ +COPY docker-entrypoint.sh /usr/local/bin/ +ENTRYPOINT ["docker-entrypoint.sh"] + +EXPOSE 4369 5671 5672 15691 15692 25672 +CMD ["rabbitmq-server"] diff --git a/4.2-rc/ubuntu/docker-entrypoint.sh b/4.2-rc/ubuntu/docker-entrypoint.sh new file mode 100755 index 00000000..c1c55b6d --- /dev/null +++ b/4.2-rc/ubuntu/docker-entrypoint.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +set -euo pipefail + +# allow the container to be started with `--user` +if [[ "$1" == rabbitmq* ]] && [ "$(id -u)" = '0' ]; then + if [ "$1" = 'rabbitmq-server' ]; then + find /var/lib/rabbitmq \! -user rabbitmq -exec chown rabbitmq '{}' + + fi + + exec gosu rabbitmq "$BASH_SOURCE" "$@" +fi + +deprecatedEnvVars=( + RABBITMQ_DEFAULT_PASS_FILE + RABBITMQ_DEFAULT_USER_FILE + RABBITMQ_MANAGEMENT_SSL_CACERTFILE + RABBITMQ_MANAGEMENT_SSL_CERTFILE + RABBITMQ_MANAGEMENT_SSL_DEPTH + RABBITMQ_MANAGEMENT_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_MANAGEMENT_SSL_KEYFILE + RABBITMQ_MANAGEMENT_SSL_VERIFY + RABBITMQ_SSL_CACERTFILE + RABBITMQ_SSL_CERTFILE + RABBITMQ_SSL_DEPTH + RABBITMQ_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_SSL_KEYFILE + RABBITMQ_SSL_VERIFY + RABBITMQ_VM_MEMORY_HIGH_WATERMARK +) +hasOldEnv= +for old in "${deprecatedEnvVars[@]}"; do + if [ -n "${!old:-}" ]; then + echo >&2 "error: $old is set but deprecated" + hasOldEnv=1 + fi +done +if [ -n "$hasOldEnv" ]; then + echo >&2 'error: deprecated environment variables detected' + echo >&2 + echo >&2 'Please use a configuration file instead; visit https://www.rabbitmq.com/configure.html to learn more' + echo >&2 + exit 1 +fi + +# if long and short hostnames are not the same, use long hostnames +if [ -z "${RABBITMQ_USE_LONGNAME:-}" ] && [ "$(hostname)" != "$(hostname -s)" ]; then + : "${RABBITMQ_USE_LONGNAME:=true}" +fi + +exec "$@" diff --git a/4.2-rc/ubuntu/management/Dockerfile b/4.2-rc/ubuntu/management/Dockerfile new file mode 100644 index 00000000..e3f7311f --- /dev/null +++ b/4.2-rc/ubuntu/management/Dockerfile @@ -0,0 +1,23 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +FROM rabbitmq:4.2-rc + +RUN set -eux; \ + rabbitmq-plugins enable --offline rabbitmq_management; \ +# make sure the metrics collector is re-enabled (disabled in the base image for Prometheus-style metrics by default) + rm -f /etc/rabbitmq/conf.d/20-management_agent.disable_metrics_collector.conf; \ +# grab "rabbitmqadmin" from inside the "rabbitmq_management-X.Y.Z" plugin folder +# see https://github.com/docker-library/rabbitmq/issues/207 + cp /plugins/rabbitmq_management-*/priv/www/cli/rabbitmqadmin /usr/local/bin/rabbitmqadmin; \ + [ -s /usr/local/bin/rabbitmqadmin ]; \ + chmod +x /usr/local/bin/rabbitmqadmin; \ + apt-get update; \ + apt-get install -y --no-install-recommends python3; \ + rm -rf /var/lib/apt/lists/*; \ + rabbitmqadmin --version + +EXPOSE 15671 15672 diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 54e1632f..00000000 --- a/Dockerfile +++ /dev/null @@ -1,59 +0,0 @@ -FROM debian:jessie - -# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added -RUN groupadd -r rabbitmq && useradd -r -d /var/lib/rabbitmq -m -g rabbitmq rabbitmq - -RUN apt-get update && apt-get install -y curl ca-certificates --no-install-recommends && rm -rf /var/lib/apt/lists/* - -# grab gosu for easy step-down from root -RUN gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 -RUN curl -o /usr/local/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/1.6/gosu-$(dpkg --print-architecture)" \ - && curl -o /usr/local/bin/gosu.asc -SL "https://github.com/tianon/gosu/releases/download/1.6/gosu-$(dpkg --print-architecture).asc" \ - && gpg --verify /usr/local/bin/gosu.asc \ - && rm /usr/local/bin/gosu.asc \ - && chmod +x /usr/local/bin/gosu - -# Add the officially endorsed Erlang debian repository: -# See: -# - http://www.erlang.org/download.html -# - https://www.erlang-solutions.com/downloads/download-erlang-otp -RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys 434975BD900CCBE4F7EE1B1ED208507CA14F4FCA -RUN echo 'deb http://packages.erlang-solutions.com/debian jessie contrib' > /etc/apt/sources.list.d/erlang.list - -# get logs to stdout (thanks @dumbbell for pushing this upstream! :D) -ENV RABBITMQ_LOGS=- RABBITMQ_SASL_LOGS=- -# https://github.com/rabbitmq/rabbitmq-server/commit/53af45bf9a162dec849407d114041aad3d84feaf - -# http://www.rabbitmq.com/install-debian.html -# "Please note that the word testing in this line refers to the state of our release of RabbitMQ, not any particular Debian distribution." -RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys F78372A06FF50C80464FC1B4F7B8CEA6056E8E56 -RUN echo 'deb http://www.rabbitmq.com/debian testing main' > /etc/apt/sources.list.d/rabbitmq.list - -ENV RABBITMQ_VERSION 3.6.0 -ENV RABBITMQ_DEBIAN_VERSION 3.6.0-1 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - erlang erlang-mnesia erlang-public-key erlang-crypto erlang-ssl erlang-asn1 erlang-inets erlang-os-mon erlang-xmerl erlang-eldap \ - rabbitmq-server=$RABBITMQ_DEBIAN_VERSION \ - && rm -rf /var/lib/apt/lists/* - -# /usr/sbin/rabbitmq-server has some irritating behavior, and only exists to "su - rabbitmq /usr/lib/rabbitmq/bin/rabbitmq-server ..." -ENV PATH /usr/lib/rabbitmq/bin:$PATH - -RUN echo '[{rabbit, [{loopback_users, []}]}].' > /etc/rabbitmq/rabbitmq.config - -# set home so that any `--user` knows where to put the erlang cookie -ENV HOME /var/lib/rabbitmq - -VOLUME /var/lib/rabbitmq - -# add a symlink to the .erlang.cookie in /root so we can "docker exec rabbitmqctl ..." without gosu -RUN ln -sf /var/lib/rabbitmq/.erlang.cookie /root/ - -RUN ln -sf /usr/lib/rabbitmq/lib/rabbitmq_server-$RABBITMQ_VERSION/plugins /plugins - -COPY docker-entrypoint.sh / -ENTRYPOINT ["/docker-entrypoint.sh"] - -EXPOSE 4369 5671 5672 25672 -CMD ["rabbitmq-server"] diff --git a/Dockerfile-alpine.template b/Dockerfile-alpine.template new file mode 100644 index 00000000..92d29f1b --- /dev/null +++ b/Dockerfile-alpine.template @@ -0,0 +1,332 @@ +# Alpine Linux is not officially supported by the RabbitMQ team -- use at your own risk! +FROM alpine:{{ .alpine.version }} as build-base + +RUN apk add --no-cache \ + build-base \ + dpkg-dev \ + dpkg \ + gnupg \ + libc-dev \ + linux-headers \ + ncurses-dev + +FROM build-base as openssl-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +# Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally +ARG PGP_KEYSERVER=keyserver.ubuntu.com +# If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, +# run the build with a different PGP_KEYSERVER, e.g. docker build --tag rabbitmq:{{ env.version }} --build-arg PGP_KEYSERVER=pgpkeys.eu {{ env.version }}/ubuntu +# For context, see https://github.com/docker-library/official-images/issues/4252 + +ENV OPENSSL_VERSION {{ .openssl.version }} +ENV OPENSSL_SOURCE_SHA256="{{ .openssl.sha256 }}" +# https://www.openssl.org/source/ +ENV OPENSSL_PGP_KEY_IDS="{{ +[ + # "OpenSSL " + # https://openssl-library.org/source/index.html + # "The current releases are signed by the OpenSSL key with fingerprint:" + # https://keys.openpgp.org/search?q=openssl%40openssl.org + "BA54 73A2 B058 7B07 FB27 CF2D 2160 94DF D0CB 81EF", + + # hack for trailing comma above + empty +] +# TODO auto-generate / scrape this list from the canonical upstream source instead (check the signature file and add an entry in the .openssl object with just the one signature that we expect to have signed this release, after cross-referencing the official OMC list?) +| map("0x" + gsub(" "; "")) | join(" ") +}}" + +ENV OTP_VERSION {{ .otp.version }} +# TODO add PGP checking when the feature will be added to Erlang/OTP's build system +# https://erlang.org/pipermail/erlang-questions/2019-January/097067.html +ENV OTP_SOURCE_SHA256="{{ .otp.sha256 }}" + +# install openssl & erlang to a path that isn't auto-checked for libs to prevent accidental use by system packages +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl + +# Install dependencies required to build Erlang/OTP from source +# https://erlang.org/doc/installation_guide/INSTALL.html +# dpkg-dev: Required to set up host & build type when compiling Erlang/OTP +# 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; \ +# /usr/local/src doesn't exist in Alpine by default + mkdir -p /usr/local/src; \ + \ + OPENSSL_SOURCE_URL="https://github.com/openssl/openssl/releases/download/openssl-$OPENSSL_VERSION/openssl-$OPENSSL_VERSION.tar.gz"; \ + OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ + OPENSSL_CONFIG_DIR="$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# 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"; \ + export GNUPGHOME="$(mktemp -d)"; \ + for key in $OPENSSL_PGP_KEY_IDS; do \ + gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \ + done; \ + gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum -c -; \ + mkdir -p "$OPENSSL_PATH"; \ + tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \ + \ +# Configure OpenSSL for compilation + cd "$OPENSSL_PATH"; \ +# OpenSSL's "config" script uses a lot of "uname"-based target detection... + apkArch="$(apk --print-arch)"; \ +# https://dl-cdn.alpinelinux.org/alpine/edge/main/ + case "$apkArch" in \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L860 (look for "linux-" and "linux64-" keys) + aarch64) opensslMachine='linux-aarch64' ;; \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L736-L766 +# https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html + armhf) opensslMachine='linux-armv4'; opensslExtraConfig='-march=armv6+fp' ;; \ + armv7) opensslMachine='linux-armv4'; opensslExtraConfig='-march=armv7-a+fp' ;; \ + ppc64le) opensslMachine='linux-ppc64le' ;; \ + riscv64) opensslMachine='linux64-riscv64' ;; \ + s390x) opensslMachine='linux64-s390x' ;; \ + x86) opensslMachine='linux-x86' ;; \ + x86_64) opensslMachine='linux-x86_64' ;; \ + *) echo >&2 "error: unsupported arch: '$apkArch'"; exit 1 ;; \ + esac; \ + MACHINE="$opensslMachine" \ + RELEASE="4.x.y-z" \ + SYSTEM='Linux' \ + BUILD='???' \ + ./Configure \ + "$opensslMachine" \ + enable-fips \ + --prefix="$OPENSSL_INSTALL_PATH_PREFIX" \ + --openssldir="$OPENSSL_CONFIG_DIR" \ + --libdir="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ +# 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) + -Wl,-rpath="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ + ${opensslExtraConfig:-} \ + ; \ +# Compile, install OpenSSL, verify that the command-line works & development headers are present + make -j "$(getconf _NPROCESSORS_ONLN)"; \ + make install_sw install_ssldirs install_fips; \ +# 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" + +# smoke test +RUN $OPENSSL_INSTALL_PATH_PREFIX/bin/openssl version + +FROM openssl-builder as erlang-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +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"; \ + \ +# Download, verify & extract OTP_SOURCE + mkdir -p "$OTP_PATH"; \ + wget --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \ + echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum -c -; \ + tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \ + \ +# Configure Erlang/OTP for compilation, disable unused features & applications +# https://erlang.org/doc/applications.html +# ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation + cd "$OTP_PATH"; \ + export ERL_TOP="$OTP_PATH"; \ + export CFLAGS='-g -O2'; \ +# 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) + export CFLAGS="$CFLAGS -Wl,-rpath=$OPENSSL_INSTALL_PATH_PREFIX/lib"; \ + hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ + buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ + dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ +# JIT is only supported on amd64 + arm64; https://github.com/erlang/otp/blob/OTP-25.3.2.2/erts/configure#L24306-L24347 + jitFlag=; \ + case "$dpkgArch" in \ + amd64 | arm64) jitFlag='--enable-jit' ;; \ + esac; \ + ./configure \ + --prefix="$ERLANG_INSTALL_PATH_PREFIX" \ + --host="$hostArch" \ + --build="$buildArch" \ + --disable-hipe \ + --disable-sctp \ + --disable-silent-rules \ + --enable-builtin-zlib \ + --enable-clock-gettime \ + --enable-hybrid-heap \ + --enable-kernel-poll \ + --enable-smp-support \ + --enable-threads \ + --with-microstate-accounting=extra \ + --with-ssl="$OPENSSL_INSTALL_PATH_PREFIX" \ + --without-common_test \ + --without-debugger \ + --without-dialyzer \ + --without-diameter \ + --without-edoc \ + --without-erl_docgen \ + --without-et \ + --without-eunit \ + --without-ftp \ + --without-hipe \ + --without-jinterface \ + --without-megaco \ + --without-observer \ + --without-odbc \ + --without-reltool \ + --without-snmp \ + --without-ssh \ + --without-tftp \ + --without-wx \ + $jitFlag \ + ; \ +# Compile & install Erlang/OTP + make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ + make install; \ + \ +# Remove unnecessary files + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name examples -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name src -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name include -exec rm -rf '{}' + + +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$PATH +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 }' +RUN erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' + +FROM alpine:{{ .alpine.version }} + +# OPENSSL/ERLANG_INSTALL_PATH_PREFIX are defined in a different stage, so define them again +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl + +COPY --from=erlang-builder $ERLANG_INSTALL_PATH_PREFIX $ERLANG_INSTALL_PATH_PREFIX +COPY --from=openssl-builder $OPENSSL_INSTALL_PATH_PREFIX $OPENSSL_INSTALL_PATH_PREFIX + +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$OPENSSL_INSTALL_PATH_PREFIX/bin:$PATH + +ENV RABBITMQ_DATA_DIR /var/lib/rabbitmq + +RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# Ensure run-time dependencies are installed + runDeps="$( \ + scanelf --needed --nobanner --format '%n#p' --recursive $ERLANG_INSTALL_PATH_PREFIX $OPENSSL_INSTALL_PATH_PREFIX \ + | tr ',' '\n' \ + | sort -u \ + | grep -v '^$\|lib\(crypto\|ssl\)' \ + | awk 'system("test -e /usr/local/lib/" $1) == 0 { next } { print "so:" $1 }' \ + )"; \ + apk add --no-cache --virtual .otp-run-deps $runDeps; \ + \ +# Check that OpenSSL still works after copying from previous builder + sed -i.ORIG -e "/\.include.*fips/ s!.*!.include $OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf!" \ + -e '/# fips =/s/.*/fips = fips_sect/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/openssl.cnf"; \ + sed -i.ORIG -e '/^activate/s/^/#/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf"; \ + [ "$(command -v openssl)" = "$OPENSSL_INSTALL_PATH_PREFIX/bin/openssl" ]; \ + openssl version; \ + openssl version -d; \ + \ +# 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 + 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 1777 "$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; \ + \ + 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 }} +# https://www.rabbitmq.com/signatures.html#importing-gpg +ENV RABBITMQ_PGP_KEY_ID 0x0A9AF2115F4687BD29803A206B73A36E6026DFCA +ENV RABBITMQ_HOME /opt/rabbitmq + +# Add RabbitMQ to PATH +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 \ + xz \ + ; \ + \ + RABBITMQ_SOURCE_URL="https://github.com/rabbitmq/rabbitmq-server/releases/download/v$RABBITMQ_VERSION/rabbitmq-server-generic-unix-latest-toolchain-$RABBITMQ_VERSION.tar.xz"; \ + RABBITMQ_PATH="/usr/local/src/rabbitmq-$RABBITMQ_VERSION"; \ + \ + wget --output-document "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_SOURCE_URL.asc"; \ + wget --output-document "$RABBITMQ_PATH.tar.xz" "$RABBITMQ_SOURCE_URL"; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$RABBITMQ_PGP_KEY_ID"; \ + gpg --batch --verify "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_PATH.tar.xz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + \ + mkdir -p "$RABBITMQ_HOME"; \ + tar --extract --file "$RABBITMQ_PATH.tar.xz" --directory "$RABBITMQ_HOME" --strip-components 1; \ + rm -rf "$RABBITMQ_PATH"*; \ +# Do not default SYS_PREFIX to RABBITMQ_HOME, leave it empty + grep -qE '^SYS_PREFIX=\$\{RABBITMQ_HOME\}$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + sed -i 's/^SYS_PREFIX=.*$/SYS_PREFIX=/' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ + \ + apk del --no-network .build-deps; \ + \ +# verify assumption of no stale cookies + [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ +# Ensure RabbitMQ was installed correctly by running a few commands that do not depend on a running server, as the rabbitmq user +# If they all succeed, it's safe to assume that things have been set up correctly + su-exec rabbitmq rabbitmqctl help; \ + su-exec rabbitmq rabbitmqctl list_ciphers; \ + su-exec rabbitmq rabbitmq-plugins list; \ +# no stale cookies + rm "$RABBITMQ_DATA_DIR/.erlang.cookie" + +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +RUN su-exec rabbitmq rabbitmq-plugins enable --offline rabbitmq_prometheus + +# Added for backwards compatibility - users can simply COPY custom plugins to /plugins +RUN ln -sf /opt/rabbitmq/plugins /plugins + +# set home so that any `--user` knows where to put the erlang cookie +ENV HOME $RABBITMQ_DATA_DIR +# Hint that the data (a.k.a. home dir) dir should be separate volume +VOLUME $RABBITMQ_DATA_DIR + +# warning: the VM is running with native name encoding of latin1 which may cause Elixir to malfunction as it expects utf8. Please ensure your locale is set to UTF-8 (which can be verified by running "locale" in your shell) +# Setting all environment variables that control language preferences, behaviour differs - https://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html#The-LANGUAGE-variable +# https://docs.docker.com/samples/library/ubuntu/#locales +ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 + +COPY --chown=rabbitmq:rabbitmq 10-defaults.conf 20-management_agent.disable_metrics_collector.conf /etc/rabbitmq/conf.d/ +COPY docker-entrypoint.sh /usr/local/bin/ +ENTRYPOINT ["docker-entrypoint.sh"] + +EXPOSE 4369 5671 5672 15691 15692 25672 +CMD ["rabbitmq-server"] diff --git a/Dockerfile-management.template b/Dockerfile-management.template new file mode 100644 index 00000000..c0d742de --- /dev/null +++ b/Dockerfile-management.template @@ -0,0 +1,24 @@ +FROM {{ + "rabbitmq:" + env.version + + if env.variant == "alpine" then "-alpine" else "" end +}} + +RUN set -eux; \ + rabbitmq-plugins enable --offline rabbitmq_management; \ +# make sure the metrics collector is re-enabled (disabled in the base image for Prometheus-style metrics by default) + rm -f /etc/rabbitmq/conf.d/20-management_agent.disable_metrics_collector.conf; \ +# grab "rabbitmqadmin" from inside the "rabbitmq_management-X.Y.Z" plugin folder +# see https://github.com/docker-library/rabbitmq/issues/207 + cp /plugins/rabbitmq_management-*/priv/www/cli/rabbitmqadmin /usr/local/bin/rabbitmqadmin; \ + [ -s /usr/local/bin/rabbitmqadmin ]; \ + chmod +x /usr/local/bin/rabbitmqadmin; \ +{{ if env.variant == "alpine" then ( -}} + apk add --no-cache python3; \ +{{ ) else ( -}} + apt-get update; \ + apt-get install -y --no-install-recommends python3; \ + rm -rf /var/lib/apt/lists/*; \ +{{ ) end -}} + rabbitmqadmin --version + +EXPOSE 15671 15672 diff --git a/Dockerfile-ubuntu.template b/Dockerfile-ubuntu.template new file mode 100644 index 00000000..07aee153 --- /dev/null +++ b/Dockerfile-ubuntu.template @@ -0,0 +1,335 @@ +# 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:{{ .ubuntu.version }} as build-base + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + build-essential \ + ca-certificates \ + gnupg \ + libncurses5-dev \ + wget + +FROM build-base as openssl-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +# Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally +ARG PGP_KEYSERVER=keyserver.ubuntu.com +# If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, +# run the build with a different PGP_KEYSERVER, e.g. docker build --tag rabbitmq:{{ env.version }} --build-arg PGP_KEYSERVER=pgpkeys.eu {{ env.version }}/ubuntu +# For context, see https://github.com/docker-library/official-images/issues/4252 + +ENV OPENSSL_VERSION {{ .openssl.version }} +ENV OPENSSL_SOURCE_SHA256="{{ .openssl.sha256 }}" +# https://www.openssl.org/source/ +ENV OPENSSL_PGP_KEY_IDS="{{ +[ + # "OpenSSL " + # https://openssl-library.org/source/index.html + # "The current releases are signed by the OpenSSL key with fingerprint:" + # https://keys.openpgp.org/search?q=openssl%40openssl.org + "BA54 73A2 B058 7B07 FB27 CF2D 2160 94DF D0CB 81EF", + + # hack for trailing comma above + empty +] +# TODO auto-generate / scrape this list from the canonical upstream source instead (check the signature file and add an entry in the .openssl object with just the one signature that we expect to have signed this release, after cross-referencing the official OMC list?) +| map("0x" + gsub(" "; "")) | join(" ") +}}" + +ENV OTP_VERSION {{ .otp.version }} +# TODO add PGP checking when the feature will be added to Erlang/OTP's build system +# https://erlang.org/pipermail/erlang-questions/2019-January/097067.html +ENV OTP_SOURCE_SHA256="{{ .otp.sha256 }}" + +# install openssl & erlang to a path that isn't auto-checked for libs to prevent accidental use by system packages +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl + +# Install dependencies required to build Erlang/OTP from source +# https://erlang.org/doc/installation_guide/INSTALL.html +# dpkg-dev: Required to set up host & build type when compiling Erlang/OTP +# 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; \ + OPENSSL_SOURCE_URL="https://github.com/openssl/openssl/releases/download/openssl-$OPENSSL_VERSION/openssl-$OPENSSL_VERSION.tar.gz"; \ + OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ + OPENSSL_CONFIG_DIR="$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# Required by the crypto & ssl Erlang/OTP applications + wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_SOURCE_URL.asc"; \ + wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz" "$OPENSSL_SOURCE_URL"; \ + export GNUPGHOME="$(mktemp -d)"; \ + for key in $OPENSSL_PGP_KEY_IDS; do \ + gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \ + done; \ + gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum --check --strict -; \ + mkdir -p "$OPENSSL_PATH"; \ + tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \ + \ +# Configure OpenSSL for compilation + cd "$OPENSSL_PATH"; \ +# without specifying "--libdir", Erlang will fail during "crypto:supports()" looking for a "pthread_atfork" function that doesn't exist (but only on arm32v7/armhf??) +# OpenSSL's "config" script uses a lot of "uname"-based target detection... + dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ +# https://deb.debian.org/debian/dists/unstable/main/ + case "$dpkgArch" in \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L860 (look for "linux-" and "linux64-" keys) + amd64) opensslMachine='linux-x86_64' ;; \ + arm64) opensslMachine='linux-aarch64' ;; \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L736-L766 +# https://wiki.debian.org/ArchitectureSpecificsMemo#Architecture_baselines +# https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html + armhf) opensslMachine='linux-armv4'; opensslExtraConfig='-march=armv7-a+fp' ;; \ + i386) opensslMachine='linux-x86' ;; \ + ppc64el) opensslMachine='linux-ppc64le' ;; \ + riscv64) opensslMachine='linux64-riscv64' ;; \ + s390x) opensslMachine='linux64-s390x' ;; \ + *) echo >&2 "error: unsupported arch: '$apkArch'"; exit 1 ;; \ + esac; \ + MACHINE="$opensslMachine" \ + RELEASE="4.x.y-z" \ + SYSTEM='Linux' \ + BUILD='???' \ + ./Configure \ + "$opensslMachine" \ + enable-fips \ + --prefix="$OPENSSL_INSTALL_PATH_PREFIX" \ + --openssldir="$OPENSSL_CONFIG_DIR" \ + --libdir="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ +# 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) + -Wl,-rpath="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ + ${opensslExtraConfig:-} \ + ; \ +# Compile, install OpenSSL, verify that the command-line works & development headers are present + make -j "$(getconf _NPROCESSORS_ONLN)"; \ + make install_sw install_ssldirs install_fips; \ + 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" + +# smoke test +RUN $OPENSSL_INSTALL_PATH_PREFIX/bin/openssl version + +FROM openssl-builder as erlang-builder + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +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"; \ + \ +# Download, verify & extract OTP_SOURCE + mkdir -p "$OTP_PATH"; \ + wget --progress dot:giga --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \ + echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum --check --strict -; \ + tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \ + \ +{{ if .otp.version | startswith("25.") or startswith("26.") then ( -}} +# backport https://github.com/erlang/otp/pull/7952 (applied upstream in OTP 27+) to fix time64 compilation issues on 32bit architectures +# see also https://bugs.debian.org/1067701, https://salsa.debian.org/erlang-team/packages/erlang/-/blob/89c4e190c6d1d7ee0133d9a8d6bf651ff1861e46/debian/patches/time64.patch + wget --output-document otp-time64.patch 'https://github.com/erlang/otp/pull/7952.patch?full_index=1'; \ + echo 'd1a0c0433a9a08c83171bedd438dd59bb336b40ec75f59edfc3a647b8b0c612d *otp-time64.patch' | sha256sum --check --strict -; \ + patch --input="$PWD/otp-time64.patch" --directory="$OTP_PATH" --strip=1; \ + rm otp-time64.patch; \ + \ +{{ ) else "" end -}} +# Configure Erlang/OTP for compilation, disable unused features & applications +# https://erlang.org/doc/applications.html +# ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation + cd "$OTP_PATH"; \ + export ERL_TOP="$OTP_PATH"; \ + 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 "$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) + export CFLAGS="$CFLAGS -Wl,-rpath=$OPENSSL_INSTALL_PATH_PREFIX/lib"; \ + hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ + buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ + dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ +# JIT is only supported on amd64 + arm64; https://github.com/erlang/otp/blob/OTP-25.3.2.2/erts/configure#L24306-L24347 + jitFlag=; \ + case "$dpkgArch" in \ + amd64 | arm64) jitFlag='--enable-jit' ;; \ + esac; \ + ./configure \ + --prefix="$ERLANG_INSTALL_PATH_PREFIX" \ + --host="$hostArch" \ + --build="$buildArch" \ + --disable-hipe \ + --disable-sctp \ + --disable-silent-rules \ + --enable-builtin-zlib \ + --enable-clock-gettime \ + --enable-hybrid-heap \ + --enable-kernel-poll \ + --enable-smp-support \ + --enable-threads \ + --with-microstate-accounting=extra \ + --with-ssl="$OPENSSL_INSTALL_PATH_PREFIX" \ + --without-common_test \ + --without-debugger \ + --without-dialyzer \ + --without-diameter \ + --without-edoc \ + --without-erl_docgen \ + --without-et \ + --without-eunit \ + --without-ftp \ + --without-hipe \ + --without-jinterface \ + --without-megaco \ + --without-observer \ + --without-odbc \ + --without-reltool \ + --without-snmp \ + --without-ssh \ + --without-tftp \ + --without-wx \ + $jitFlag \ + ; \ + \ +# Compile & install Erlang/OTP + make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ + make install; \ + \ +# Remove unnecessary files + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name examples -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name src -exec rm -rf '{}' +; \ + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name include -exec rm -rf '{}' + + +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$PATH +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 }' +RUN erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' + +FROM ubuntu:{{ .ubuntu.version }} + +# OPENSSL/ERLANG_INSTALL_PATH_PREFIX are defined in a different stage, so define them again +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl +COPY --from=erlang-builder $ERLANG_INSTALL_PATH_PREFIX $ERLANG_INSTALL_PATH_PREFIX +COPY --from=openssl-builder $OPENSSL_INSTALL_PATH_PREFIX $OPENSSL_INSTALL_PATH_PREFIX + +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$OPENSSL_INSTALL_PATH_PREFIX/bin:$PATH + +ENV RABBITMQ_DATA_DIR /var/lib/rabbitmq + +RUN set -eux; \ +# Configure OpenSSL to use system certs + ln -vsf /etc/ssl/certs /etc/ssl/private "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# Check that OpenSSL still works after copying from previous builder + ldconfig; \ + sed -i.ORIG -e "/\.include.*fips/ s!.*!.include $OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf!" \ + -e '/# fips =/s/.*/fips = fips_sect/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/openssl.cnf"; \ + sed -i.ORIG -e '/^activate/s/^/#/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf"; \ + [ "$(command -v openssl)" = "$OPENSSL_INSTALL_PATH_PREFIX/bin/openssl" ]; \ + openssl version; \ + openssl version -d; \ + \ +# 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; \ + chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ + chmod 1777 "$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 + +# Use the latest stable RabbitMQ release (https://www.rabbitmq.com/download.html) +ENV RABBITMQ_VERSION {{ .version }} +# https://www.rabbitmq.com/signatures.html#importing-gpg +ENV RABBITMQ_PGP_KEY_ID 0x0A9AF2115F4687BD29803A206B73A36E6026DFCA +ENV RABBITMQ_HOME /opt/rabbitmq + +# Add RabbitMQ to PATH +ENV PATH $RABBITMQ_HOME/sbin:$PATH + +# Install RabbitMQ +RUN set -eux; \ + 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 \ + ; \ + rm -rf /var/lib/apt/lists/*; \ + \ + RABBITMQ_SOURCE_URL="https://github.com/rabbitmq/rabbitmq-server/releases/download/v$RABBITMQ_VERSION/rabbitmq-server-generic-unix-latest-toolchain-$RABBITMQ_VERSION.tar.xz"; \ + RABBITMQ_PATH="/usr/local/src/rabbitmq-$RABBITMQ_VERSION"; \ + \ + wget --progress dot:giga --output-document "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_SOURCE_URL.asc"; \ + wget --progress dot:giga --output-document "$RABBITMQ_PATH.tar.xz" "$RABBITMQ_SOURCE_URL"; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$RABBITMQ_PGP_KEY_ID"; \ + gpg --batch --verify "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_PATH.tar.xz"; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + \ + mkdir -p "$RABBITMQ_HOME"; \ + tar --extract --file "$RABBITMQ_PATH.tar.xz" --directory "$RABBITMQ_HOME" --strip-components 1; \ + rm -rf "$RABBITMQ_PATH"*; \ +# Do not default SYS_PREFIX to RABBITMQ_HOME, leave it empty + grep -qE '^SYS_PREFIX=\$\{RABBITMQ_HOME\}$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + sed -i 's/^SYS_PREFIX=.*$/SYS_PREFIX=/' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ + chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ + \ + apt-mark auto '.*' > /dev/null; \ + apt-mark manual $savedAptMark; \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + \ +# verify assumption of no stale cookies + [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ +# Ensure RabbitMQ was installed correctly by running a few commands that do not depend on a running server, as the rabbitmq user +# If they all succeed, it's safe to assume that things have been set up correctly + gosu rabbitmq rabbitmqctl help; \ + gosu rabbitmq rabbitmqctl list_ciphers; \ + gosu rabbitmq rabbitmq-plugins list; \ +# no stale cookies + rm "$RABBITMQ_DATA_DIR/.erlang.cookie" + +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +RUN gosu rabbitmq rabbitmq-plugins enable --offline rabbitmq_prometheus + +# Added for backwards compatibility - users can simply COPY custom plugins to /plugins +RUN ln -sf /opt/rabbitmq/plugins /plugins + +# set home so that any `--user` knows where to put the erlang cookie +ENV HOME $RABBITMQ_DATA_DIR +# Hint that the data (a.k.a. home dir) dir should be separate volume +VOLUME $RABBITMQ_DATA_DIR + +# warning: the VM is running with native name encoding of latin1 which may cause Elixir to malfunction as it expects utf8. Please ensure your locale is set to UTF-8 (which can be verified by running "locale" in your shell) +# Setting all environment variables that control language preferences, behaviour differs - https://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html#The-LANGUAGE-variable +# https://docs.docker.com/samples/library/ubuntu/#locales +ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 + +COPY --chown=rabbitmq:rabbitmq 10-defaults.conf 20-management_agent.disable_metrics_collector.conf /etc/rabbitmq/conf.d/ +COPY docker-entrypoint.sh /usr/local/bin/ +ENTRYPOINT ["docker-entrypoint.sh"] + +EXPOSE 4369 5671 5672 15691 15692 25672 +CMD ["rabbitmq-server"] diff --git a/LICENSE b/LICENSE index 25714b8b..fbab368d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014-2015 Docker, Inc. +Copyright (c) 2014 Docker, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.md b/README.md index 2a9e4e80..3c7c1f84 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,15 @@ -# About this Repo +# https://github.com/docker-library/rabbitmq -This is the Git repo of the Docker [official image](https://docs.docker.com/docker-hub/official_repos/) for [rabbitmq](https://registry.hub.docker.com/_/rabbitmq/), maintained by Docker, Inc. See [the Docker Hub page](https://registry.hub.docker.com/_/rabbitmq/) for the full readme on how to use this Docker image and for information regarding contributing and issues. +## Maintained by: [the Docker Community](https://github.com/docker-library/rabbitmq) -The full readme is generated over in [docker-library/docs](https://github.com/docker-library/docs), specificially in [docker-library/docs/rabbitmq](https://github.com/docker-library/docs/tree/master/rabbitmq). +This is the Git repo of the [Docker "Official Image"](https://github.com/docker-library/official-images#what-are-official-images) for [`rabbitmq`](https://hub.docker.com/_/rabbitmq/) (not to be confused with any official `rabbitmq` image provided by `rabbitmq` upstream). See [the Docker Hub page](https://hub.docker.com/_/rabbitmq/) for the full readme on how to use this Docker image and for information regarding contributing and issues. -See a change merged here that doesn't show up on the Docker Hub yet? Check [the "library/rabbitmq" manifest file in the docker-library/official-images repo](https://github.com/docker-library/official-images/blob/master/library/rabbitmq), especially [PRs with the "library/rabbitmq" label on that repo](https://github.com/docker-library/official-images/labels/library%2Frabbitmq). For more information about the official images process, see the [docker-library/official-images readme](https://github.com/docker-library/official-images/blob/master/README.md). +The [full image description on Docker Hub](https://hub.docker.com/_/rabbitmq/) is generated/maintained over in [the docker-library/docs repository](https://github.com/docker-library/docs), specifically in [the `rabbitmq` directory](https://github.com/docker-library/docs/tree/master/rabbitmq). -[![Travis CI](https://img.shields.io/travis/docker-library/rabbitmq/master.svg)](https://travis-ci.org/docker-library/rabbitmq/branches) +## See a change merged here that doesn't show up on Docker Hub yet? + +For more information about the full official images change lifecycle, see [the "An image's source changed in Git, now what?" FAQ entry](https://github.com/docker-library/faq#an-images-source-changed-in-git-now-what). + +For outstanding `rabbitmq` image PRs, check [PRs with the "library/rabbitmq" label on the official-images repository](https://github.com/docker-library/official-images/labels/library%2Frabbitmq). For the current "source of truth" for [`rabbitmq`](https://hub.docker.com/_/rabbitmq/), see [the `library/rabbitmq` file in the official-images repository](https://github.com/docker-library/official-images/blob/master/library/rabbitmq). diff --git a/apply-templates.sh b/apply-templates.sh new file mode 100755 index 00000000..3d1091c4 --- /dev/null +++ b/apply-templates.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +[ -f versions.json ] # run "versions.sh" first + +cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" + +jqt='.jq-template.awk' +if [ -n "${BASHBREW_SCRIPTS:-}" ]; then + jqt="$BASHBREW_SCRIPTS/jq-template.awk" +elif [ "$BASH_SOURCE" -nt "$jqt" ]; then + # https://github.com/docker-library/bashbrew/blob/master/scripts/jq-template.awk + wget -qO "$jqt" 'https://github.com/docker-library/bashbrew/raw/9f6a35772ac863a0241f147c820354e4008edf38/scripts/jq-template.awk' +fi + +if [ "$#" -eq 0 ]; then + versions="$(jq -r 'keys | map(@sh) | join(" ")' versions.json)" + eval "set -- $versions" +fi + +generated_warning() { + cat <<-EOH + # + # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" + # + # PLEASE DO NOT EDIT IT DIRECTLY. + # + + EOH +} + +for version; do + export version + + if [ -d "$version" ]; then + rm -rf "$version" + fi + + if jq -e '.[env.version] | not' versions.json > /dev/null; then + echo "skipping $version ..." + continue + fi + + for variant in alpine ubuntu; do + export variant + + echo "processing $version/$variant ..." + + mkdir -p "$version/$variant" + + { + generated_warning + gawk -f "$jqt" "Dockerfile-$variant.template" + } > "$version/$variant/Dockerfile" + + cp -f docker-entrypoint.sh conf.d/*.conf "$version/$variant/" + + if [ "$variant" = 'alpine' ]; then + sed -i -e 's/gosu/su-exec/g' "$version/$variant/docker-entrypoint.sh" + fi + + echo "processing $version/$variant/management ..." + + mkdir -p "$version/$variant/management" + + { + generated_warning + gawk -f "$jqt" Dockerfile-management.template + } > "$version/$variant/management/Dockerfile" + done +done diff --git a/conf.d/10-defaults.conf b/conf.d/10-defaults.conf new file mode 100644 index 00000000..27973c74 --- /dev/null +++ b/conf.d/10-defaults.conf @@ -0,0 +1,12 @@ +## DEFAULT SETTINGS ARE NOT MEANT TO BE TAKEN STRAIGHT INTO PRODUCTION +## see https://www.rabbitmq.com/configure.html for further information +## on configuring RabbitMQ + +## allow access to the guest user from anywhere on the network +## https://www.rabbitmq.com/access-control.html#loopback-users +## https://www.rabbitmq.com/production-checklist.html#users +loopback_users.guest = false + +## Send all logs to stdout/TTY. Necessary to see logs when running via +## a container +log.console = true diff --git a/conf.d/20-management_agent.disable_metrics_collector.conf b/conf.d/20-management_agent.disable_metrics_collector.conf new file mode 100644 index 00000000..6eb7a86c --- /dev/null +++ b/conf.d/20-management_agent.disable_metrics_collector.conf @@ -0,0 +1,2 @@ +# Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) +management_agent.disable_metrics_collector = true diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 85a05c03..c1c55b6d 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -1,144 +1,50 @@ -#!/bin/bash -set -e +#!/usr/bin/env bash +set -euo pipefail # allow the container to be started with `--user` -if [ "$1" = 'rabbitmq-server' -a "$(id -u)" = '0' ]; then - chown -R rabbitmq /var/lib/rabbitmq - exec gosu rabbitmq "$BASH_SOURCE" "$@" -fi - -ssl= -if [ "$RABBITMQ_SSL_CERT_FILE" -a "$RABBITMQ_SSL_KEY_FILE" -a "$RABBITMQ_SSL_CA_FILE" ]; then - ssl=1 -fi +if [[ "$1" == rabbitmq* ]] && [ "$(id -u)" = '0' ]; then + if [ "$1" = 'rabbitmq-server' ]; then + find /var/lib/rabbitmq \! -user rabbitmq -exec chown rabbitmq '{}' + + fi -# If long & short hostnames are not the same, use long hostnames -if [ "$(hostname)" != "$(hostname -s)" ]; then - export RABBITMQ_USE_LONGNAME=true + exec gosu rabbitmq "$BASH_SOURCE" "$@" fi -if [ "$RABBITMQ_ERLANG_COOKIE" ]; then - cookieFile='/var/lib/rabbitmq/.erlang.cookie' - if [ -e "$cookieFile" ]; then - if [ "$(cat "$cookieFile" 2>/dev/null)" != "$RABBITMQ_ERLANG_COOKIE" ]; then - echo >&2 - echo >&2 "warning: $cookieFile contents do not match RABBITMQ_ERLANG_COOKIE" - echo >&2 - fi - else - echo "$RABBITMQ_ERLANG_COOKIE" > "$cookieFile" - chmod 600 "$cookieFile" +deprecatedEnvVars=( + RABBITMQ_DEFAULT_PASS_FILE + RABBITMQ_DEFAULT_USER_FILE + RABBITMQ_MANAGEMENT_SSL_CACERTFILE + RABBITMQ_MANAGEMENT_SSL_CERTFILE + RABBITMQ_MANAGEMENT_SSL_DEPTH + RABBITMQ_MANAGEMENT_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_MANAGEMENT_SSL_KEYFILE + RABBITMQ_MANAGEMENT_SSL_VERIFY + RABBITMQ_SSL_CACERTFILE + RABBITMQ_SSL_CERTFILE + RABBITMQ_SSL_DEPTH + RABBITMQ_SSL_FAIL_IF_NO_PEER_CERT + RABBITMQ_SSL_KEYFILE + RABBITMQ_SSL_VERIFY + RABBITMQ_VM_MEMORY_HIGH_WATERMARK +) +hasOldEnv= +for old in "${deprecatedEnvVars[@]}"; do + if [ -n "${!old:-}" ]; then + echo >&2 "error: $old is set but deprecated" + hasOldEnv=1 fi +done +if [ -n "$hasOldEnv" ]; then + echo >&2 'error: deprecated environment variables detected' + echo >&2 + echo >&2 'Please use a configuration file instead; visit https://www.rabbitmq.com/configure.html to learn more' + echo >&2 + exit 1 fi -if [ "$1" = 'rabbitmq-server' ]; then - configs=( - # https://www.rabbitmq.com/configure.html - default_pass - default_user - default_vhost - ssl_ca_file - ssl_cert_file - ssl_key_file - ) - - haveConfig= - for conf in "${configs[@]}"; do - var="RABBITMQ_${conf^^}" - val="${!var}" - if [ "$val" ]; then - haveConfig=1 - break - fi - done - - if [ "$haveConfig" ]; then - cat > /etc/rabbitmq/rabbitmq.config <<-'EOH' - [ - {rabbit, - [ - EOH - - if [ "$ssl" ]; then - cat >> /etc/rabbitmq/rabbitmq.config <<-EOS - { tcp_listeners, [ ] }, - { ssl_listeners, [ 5671 ] }, - { ssl_options, [ - { certfile, "$RABBITMQ_SSL_CERT_FILE" }, - { keyfile, "$RABBITMQ_SSL_KEY_FILE" }, - { cacertfile, "$RABBITMQ_SSL_CA_FILE" }, - { verify, verify_peer }, - { fail_if_no_peer_cert, true } ] }, - EOS - else - cat >> /etc/rabbitmq/rabbitmq.config <<-EOS - { tcp_listeners, [ 5672 ] }, - { ssl_listeners, [ ] }, - EOS - fi - - for conf in "${configs[@]}"; do - [ "${conf#ssl_}" = "$conf" ] || continue - var="RABBITMQ_${conf^^}" - val="${!var}" - [ "$val" ] || continue - cat >> /etc/rabbitmq/rabbitmq.config <<-EOC - {$conf, <<"$val">>}, - EOC - done - cat >> /etc/rabbitmq/rabbitmq.config <<-'EOF' - {loopback_users, []} - EOF - - # If management plugin is installed, then generate config consider this - if [ "$(rabbitmq-plugins list -m -e rabbitmq_management)" ]; then - cat >> /etc/rabbitmq/rabbitmq.config <<-'EOF' - ] - }, - { rabbitmq_management, [ - { listener, [ - EOF - - if [ "$ssl" ]; then - cat >> /etc/rabbitmq/rabbitmq.config <<-EOS - { port, 15671 }, - { ssl, true }, - { ssl_opts, [ - { certfile, "$RABBITMQ_SSL_CERT_FILE" }, - { keyfile, "$RABBITMQ_SSL_KEY_FILE" }, - { cacertfile, "$RABBITMQ_SSL_CA_FILE" }, - { verify, verify_none }, - { fail_if_no_peer_cert, false } ] } ] } - EOS - else - cat >> /etc/rabbitmq/rabbitmq.config <<-EOS - { port, 15672 }, - { ssl, false } - ] - } - EOS - fi - fi - - cat >> /etc/rabbitmq/rabbitmq.config <<-'EOF' - ] - } - ]. - EOF - fi - - if [ "$ssl" ]; then - # Create combined cert - cat "$RABBITMQ_SSL_CERT_FILE" "$RABBITMQ_SSL_KEY_FILE" > /tmp/combined.pem - chmod 0400 /tmp/combined.pem - - # More ENV vars for make clustering happiness - # we don't handle clustering in this script, but these args should ensure - # clustered SSL-enabled members will talk nicely - export ERL_SSL_PATH="$(erl -eval 'io:format("~p", [code:lib_dir(ssl, ebin)]),halt().' -noshell)" - export RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="-pa '$ERL_SSL_PATH' -proto_dist inet_tls -ssl_dist_opt server_certfile /tmp/combined.pem -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true" - export RABBITMQ_CTL_ERL_ARGS="$RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS" - fi +# if long and short hostnames are not the same, use long hostnames +if [ -z "${RABBITMQ_USE_LONGNAME:-}" ] && [ "$(hostname)" != "$(hostname -s)" ]; then + : "${RABBITMQ_USE_LONGNAME:=true}" fi exec "$@" diff --git a/generate-stackbrew-library.sh b/generate-stackbrew-library.sh index b9c480c5..711b474b 100755 --- a/generate-stackbrew-library.sh +++ b/generate-stackbrew-library.sh @@ -1,35 +1,169 @@ -#!/bin/bash -set -e +#!/usr/bin/env bash +set -Eeuo pipefail +defaultVariant='ubuntu' + +self="$(basename "$BASH_SOURCE")" cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" -url='git://github.com/docker-library/rabbitmq' +if [ "$#" -eq 0 ]; then + versions="$(jq -r ' + to_entries + # sort version numbers with highest first + | sort_by(.key | split("[.-]"; "") | map(tonumber? // .)) + | reverse + | map(if .value then .key | @sh else empty end) + | join(" ") + ' versions.json)" + eval "set -- $versions" +fi -echo '# maintainer: InfoSiftr (@infosiftr)' +# get the most recent commit which modified any of "$@" +fileCommit() { + git log -1 --format='format:%H' HEAD -- "$@" +} -commit="$(git log -1 --format='format:%H' -- Dockerfile $(awk 'toupper($1) == "COPY" { for (i = 2; i < NF; i++) { print $i } }' Dockerfile))" -fullVersion="$(grep -m1 'ENV RABBITMQ_VERSION ' Dockerfile | cut -d' ' -f3)" +# get the most recent commit which modified "$1/Dockerfile" or any file COPY'd from "$1/Dockerfile" +dirCommit() { + local dir="$1"; shift + ( + cd "$dir" + fileCommit \ + Dockerfile \ + $(git show HEAD:./Dockerfile | awk ' + /^COPY/ { + for (i = 2; i < NF; i++) { + if ($i ~ /^--from=/) { + next + } + print $i + } + } + ') + ) +} -versionAliases=() -while [ "${fullVersion%.*}" != "$fullVersion" ]; do - versionAliases+=( $fullVersion ) - fullVersion="${fullVersion%.*}" -done -versionAliases+=( $fullVersion latest ) +getArches() { + local repo="$1"; shift + local officialImagesBase="${BASHBREW_LIBRARY:-https://github.com/docker-library/official-images/raw/HEAD/library}/" -echo -for va in "${versionAliases[@]}"; do - echo "$va: ${url}@${commit}" -done + local parentRepoToArchesStr + parentRepoToArchesStr="$( + find -name 'Dockerfile' -exec awk -v officialImagesBase="$officialImagesBase" ' + /^FROM/ { + if (index($2, ":") > 0 && index($2, "'"$repo"'") == 0) { + printf "%s%s\n", officialImagesBase, $2 + } + }' '{}' + | sort -u \ + | xargs -r bashbrew cat --format '["{{ .RepoName }}:{{ .TagName }}"]="{{ join " " .TagEntry.Architectures }}"' + )" + eval "declare -g -A parentRepoToArches=( $parentRepoToArchesStr )" +} +getArches 'rabbitmq' + +cat <<-EOH +# this file is generated via https://github.com/docker-library/rabbitmq/blob/$(fileCommit "$self")/$self + +Maintainers: Tianon Gravi (@tianon), + Joseph Ferguson (@yosifkit) +GitRepo: https://github.com/docker-library/rabbitmq.git +Builder: buildkit +EOH + +# prints "$2$1$3$1...$N" +join() { + local sep="$1"; shift + local out; printf -v out "${sep//%/%%}%s" "$@" + echo "${out#$sep}" +} + +declare -A usedAliases=() + +for version; do + export version + rcVersion="${version%-rc}" + + if ! fullVersion="$(jq -er '.[env.version] | if . then .version else empty end' versions.json)"; then + # support running "generate-stackbrew-library.sh" on a singular "null" version ("3.10-rc" when the RC is older than the GA release, for example) + continue + fi + + # if this is a "-rc" release, let's make sure the release it contains isn't already GA (and thus something we should not publish anymore) + export rcVersion + if [ "$rcVersion" != "$version" ] && rcFullVersion="$(jq -r '.[env.rcVersion].version // ""' versions.json)" && [ -n "$rcFullVersion" ]; then + latestVersion="$({ echo "$fullVersion"; echo "$rcFullVersion"; } | sort -V | tail -1)" + if [[ "$fullVersion" == "$rcFullVersion"* ]] || [ "$latestVersion" = "$rcFullVersion" ]; then + # "x.y.z-rc1" == x.y.z* + continue + fi + fi + + versionAliases=() + if [ "$version" = "$rcVersion" ]; then + while [ "$fullVersion" != "$version" -a "${fullVersion%[.-]*}" != "$fullVersion" ]; do + versionAliases+=( "$fullVersion" ) + fullVersion="${fullVersion%[.-]*}" + done + else + versionAliases+=( "$fullVersion" ) + fi + versionAliases+=( $version ) + + if [ "$version" = "$rcVersion" ]; then + for tagAlias in "${fullVersion%%.*}" latest; do + if [ -z "${usedAliases[$tagAlias]:-}" ]; then + versionAliases+=( "$tagAlias" ) + usedAliases["$tagAlias"]="$version" + fi + done + fi -for variant in management; do - echo - for va in "${versionAliases[@]}"; do - if [ "$va" = 'latest' ]; then - va="$variant" + for variant in ubuntu alpine; do + dir="$version/$variant" + commit="$(dirCommit "$dir")" + + if [ "$variant" = "$defaultVariant" ]; then + variantAliases=( "${versionAliases[@]}" ) else - va="$va-$variant" + variantAliases=( "${versionAliases[@]/%/-$variant}" ) + variantAliases=( "${variantAliases[@]//latest-/}" ) fi - echo "$va: ${url}@${commit} $variant" + + variantParent="$(awk ' + /^FROM/ { + if (index($2, ":") > 0) { + print $2 + exit 0 + } + }' "$dir/Dockerfile")" + variantArches="${parentRepoToArches[$variantParent]}" + + echo + cat <<-EOE + Tags: $(join ', ' "${variantAliases[@]}") + Architectures: $(join ', ' $variantArches) + GitCommit: $commit + Directory: $dir + EOE + + for subVariant in management; do + subDir="$dir/$subVariant" + commit="$(dirCommit "$subDir")" + + subVariantAliases=( "${versionAliases[@]/%/-$subVariant}" ) + subVariantAliases=( "${subVariantAliases[@]//latest-/}" ) + + if [ "$variant" != "$defaultVariant" ]; then + subVariantAliases=( "${subVariantAliases[@]/%/-$variant}" ) + fi + + echo + cat <<-EOE + Tags: $(join ', ' "${subVariantAliases[@]}") + Architectures: $(join ', ' $variantArches) + GitCommit: $commit + Directory: $subDir + EOE + done done done diff --git a/management/Dockerfile b/management/Dockerfile deleted file mode 100644 index 48727d2d..00000000 --- a/management/Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM rabbitmq - -RUN rabbitmq-plugins enable --offline rabbitmq_management - -EXPOSE 15671 15672 diff --git a/update.sh b/update.sh index 4edce382..bac2d758 100755 --- a/update.sh +++ b/update.sh @@ -1,12 +1,7 @@ -#!/bin/bash -set -e +#!/usr/bin/env bash +set -Eeuo pipefail cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" -debianVersion="$(curl -sSL 'http://www.rabbitmq.com/debian/dists/testing/main/binary-amd64/Packages' | grep -m1 -A10 '^Package: rabbitmq-server$' | grep -m1 '^Version: ' | cut -d' ' -f2)" - -rabbitmqVersion="${debianVersion%%-*}" - -set -x -sed -ri 's/^(ENV RABBITMQ_VERSION) .*/\1 '"$rabbitmqVersion"'/' Dockerfile -sed -ri 's/^(ENV RABBITMQ_DEBIAN_VERSION) .*/\1 '"$debianVersion"'/' Dockerfile +./versions.sh "$@" +./apply-templates.sh "$@" diff --git a/versions.json b/versions.json new file mode 100644 index 00000000..163e2226 --- /dev/null +++ b/versions.json @@ -0,0 +1,74 @@ +{ + "3.13": { + "alpine": { + "version": "3.22" + }, + "openssl": { + "sha256": "d319da6aecde3aa6f426b44bbf997406d95275c5c59ab6f6ef53caaa079f456f", + "version": "3.1.8" + }, + "otp": { + "sha256": "28e6d63d82927f132d56289dd3c428ef8bce6bf2283c8549aa0a7afca1a8fe3b", + "version": "26.2.5.15" + }, + "ubuntu": { + "version": "24.04" + }, + "version": "3.13.7" + }, + "3.13-rc": null, + "4.0": { + "alpine": { + "version": "3.22" + }, + "openssl": { + "sha256": "9d62c00a5a6903740c8703f0e006257f429d565d3b91ac1a9bd4a4c700002e01", + "version": "3.3.5" + }, + "otp": { + "sha256": "597618c75890e8e606033bc8dbf6ec87fdf4e892c10b4912ae3c9a4f01384579", + "version": "27.3.4.3" + }, + "ubuntu": { + "version": "24.04" + }, + "version": "4.0.9" + }, + "4.0-rc": null, + "4.1": { + "alpine": { + "version": "3.22" + }, + "openssl": { + "sha256": "9d62c00a5a6903740c8703f0e006257f429d565d3b91ac1a9bd4a4c700002e01", + "version": "3.3.5" + }, + "otp": { + "sha256": "597618c75890e8e606033bc8dbf6ec87fdf4e892c10b4912ae3c9a4f01384579", + "version": "27.3.4.3" + }, + "ubuntu": { + "version": "24.04" + }, + "version": "4.1.4" + }, + "4.1-rc": null, + "4.2": null, + "4.2-rc": { + "alpine": { + "version": "3.22" + }, + "openssl": { + "sha256": "9d62c00a5a6903740c8703f0e006257f429d565d3b91ac1a9bd4a4c700002e01", + "version": "3.3.5" + }, + "otp": { + "sha256": "597618c75890e8e606033bc8dbf6ec87fdf4e892c10b4912ae3c9a4f01384579", + "version": "27.3.4.3" + }, + "ubuntu": { + "version": "24.04" + }, + "version": "4.2.0-beta.4" + } +} diff --git a/versions.sh b/versions.sh new file mode 100755 index 00000000..fadef051 --- /dev/null +++ b/versions.sh @@ -0,0 +1,198 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +declare -A alpineVersions=( + [3.13]='3.22' + [4.0]='3.22' + [4.1]='3.22' + [4.2]='3.22' +) + +declare -A ubuntuVersions=( + [3.13]='24.04' + [4.0]='24.04' + [4.1]='24.04' + [4.2]='24.04' +) + +# https://www.rabbitmq.com/which-erlang.html ("Maximum supported Erlang/OTP") +declare -A otpMajors=( + [3.13]='26' + [4.0]='27' + [4.1]='27' + [4.2]='27' +) + +# https://www.openssl.org/policies/releasestrat.html +# https://www.openssl.org/source/ +declare -A opensslMajors=( + [3.13]='3.1' + [4.0]='3.3' + [4.1]='3.3' + [4.2]='3.3' +) + +cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" + +versions=( "$@" ) +if [ ${#versions[@]} -eq 0 ]; then + versions=( "${!otpMajors[@]}" ) + # try RC releases after doing the non-RCs so we can check whether they're newer (and thus whether we should care) + versions+=( "${versions[@]/%/-rc}" ) + json='{}' +else + json="$(< versions.json)" +fi +versions=( "${versions[@]%/}" ) + +for version in "${versions[@]}"; do + export version + + rcVersion="${version%-rc}" + rcGrepV='-v' + if [ "$rcVersion" != "$version" ]; then + rcGrepV= + fi + rcGrepV+=' -E' + rcGrepExpr='beta|milestone|rc' + + githubTags=( $( + git ls-remote --tags https://github.com/rabbitmq/rabbitmq-server.git \ + "refs/tags/v${rcVersion}"{'','.*','-*','^*'} \ + | cut -d'/' -f3- \ + | cut -d'^' -f1 \ + | { grep $rcGrepV -- "$rcGrepExpr" || :; } \ + | sort -urV + ) ) + + fullVersion= + githubTag= + for possibleTag in "${githubTags[@]}"; do + fullVersion="$( + { + # thanks GitHub... + wget -qO- "https://github.com/rabbitmq/rabbitmq-server/releases/expanded_assets/$possibleTag" \ + || wget -qO- "https://github.com/rabbitmq/rabbitmq-server/releases/tag/$possibleTag" + } | grep -oE "/rabbitmq-server-generic-unix-${rcVersion}([.-].+)?[.]tar[.]xz" \ + | head -1 \ + | sed -r "s/^.*(${rcVersion}.*)[.]tar[.]xz/\1/" \ + || : + )" + if [ -n "$fullVersion" ]; then + githubTag="$possibleTag" + break + fi + done + if [ -z "$fullVersion" ] || [ -z "$githubTag" ]; then + echo >&2 "warning: failed to get full version for '$version'; skipping" + continue + fi + export fullVersion + + # if this is a "-rc" release, let's make sure the release it contains isn't already GA (and thus something we should not publish anymore) + export rcVersion + if [ "$rcVersion" != "$version" ] && rcFullVersion="$(jq <<<"$json" -r '.[env.rcVersion].version // ""')" && [ -n "$rcFullVersion" ]; then + latestVersion="$({ echo "$fullVersion"; echo "$rcFullVersion"; } | sort -V | tail -1)" + if [[ "$fullVersion" == "$rcFullVersion"* ]] || [ "$latestVersion" = "$rcFullVersion" ]; then + # "x.y.z-rc1" == x.y.z* + echo >&2 "warning: skipping/removing '$version' ('$rcVersion' is at '$rcFullVersion' which is newer than '$fullVersion')" + continue + fi + fi + + otpMajor="${otpMajors[$rcVersion]}" + otpVersions=( $( + git ls-remote --tags https://github.com/erlang/otp.git \ + "refs/tags/OTP-$otpMajor.*"\ + | cut -d'/' -f3- \ + | cut -d'^' -f1 \ + | cut -d- -f2- \ + | sort -urV + ) ) + otpVersion= + for possibleVersion in "${otpVersions[@]}"; do + if otpSourceSha256="$( + wget -qO- "https://github.com/erlang/otp/releases/download/OTP-$possibleVersion/SHA256.txt" \ + | awk -v v="$possibleVersion" '$2 == "otp_src_" v ".tar.gz" { print $1 }' + )"; then + otpVersion="$possibleVersion" + break + fi + done + if [ -z "$otpVersion" ]; then + echo >&2 "warning: failed to get Erlang/OTP version for '$version' ($fullVersion); skipping" + continue + fi + export otpVersion otpSourceSha256 + + opensslMajor="${opensslMajors[$rcVersion]}" + # grab versions from upstream and ignore any alpha/beta releases + opensslVersions=( $( + git ls-remote --tags https://github.com/openssl/openssl.git \ + "refs/tags/openssl-$opensslMajor.*"\ + | cut -d'/' -f3- \ + | cut -d'^' -f1 \ + | cut -d- -f2- \ + | grep -vE -- '-[A-Za-z]+' \ + | sort -urV + ) ) + opensslVersion= + for possibleVersion in "${opensslVersions[@]}"; do + if opensslSourceSha256="$(wget -qO- "https://github.com/openssl/openssl/releases/download/openssl-$possibleVersion/openssl-$possibleVersion.tar.gz.sha256")"; then + opensslVersion="$possibleVersion" + break + fi + done + if [ -z "$opensslVersion" ]; then + echo >&2 "warning: failed to get OpenSSL version for '$version' ($fullVersion); skipping" + continue + fi + export opensslVersion opensslSourceSha256 + + # OpenSSL 3.0.5's sha256 file starts with a single space 😬 + opensslSourceSha256="${opensslSourceSha256# }" + # OpenSSL 3.1.8+ and 3.3.3+ now include the filename + opensslSourceSha256="${opensslSourceSha256%% *}" + + alpineVersion="${alpineVersions[$rcVersion]}" + export alpineVersion + + ubuntuVersion="${ubuntuVersions[$rcVersion]}" + export ubuntuVersion + + echo "$version: $fullVersion (otp $otpVersion, openssl $opensslVersion, alpine, $alpineVersion, ubuntu $ubuntuVersion)" + + json="$( + jq <<<"$json" -c ' + .[env.version] = { + version: env.fullVersion, + openssl: { + version: env.opensslVersion, + sha256: env.opensslSourceSha256, + }, + otp: { + version: env.otpVersion, + sha256: env.otpSourceSha256, + }, + alpine: { + version: env.alpineVersion + }, + ubuntu: { + version: env.ubuntuVersion + }, + } + ' + )" + + # make sure RCs and releases have corresponding pairs + json="$(jq <<<"$json" -c ' + .[ + env.rcVersion + + if env.version == env.rcVersion then + "-rc" + else "" end + ] //= null + ')" +done + +jq <<<"$json" -S . > versions.json