From 2d945a17bf9b8445d572f5c8770b25a1dc6b5fbd Mon Sep 17 00:00:00 2001 From: Luke Bakken Date: Sat, 11 Jul 2026 07:08:08 -0700 Subject: [PATCH] Add Amazon Linux 2023 OS variant Add an amazonlinux (AL2023) variant alongside ubuntu and alpine for RabbitMQ 4.0-4.3, building OpenSSL and Erlang/OTP from source into /opt and installing RabbitMQ from the generic-unix release. - Dockerfile-amazonlinux.template: dnf-based multi-stage build mirroring the ubuntu/alpine builder stages; final image matches the ubuntu runtime toolset (keeps tar/find/gosu/hostname/ps, purges wget/xz). - versions.sh / versions.json: amazonlinuxVersions pin (2023). - apply-templates.sh, generate-stackbrew-library.sh: amazonlinux added to both variant loops. - Dockerfile-management.template: amazonlinux branch for rabbitmqadmin. - AGENTS.md: orientation for future agents, including the AL2023 quirks learned while adding the variant. --- 4.0/amazonlinux/10-defaults.conf | 12 + ...ement_agent.disable_metrics_collector.conf | 2 + 4.0/amazonlinux/Dockerfile | 308 +++++++++++++++++ 4.0/amazonlinux/docker-entrypoint.sh | 50 +++ 4.0/amazonlinux/management/Dockerfile | 38 +++ 4.1/amazonlinux/10-defaults.conf | 12 + ...ement_agent.disable_metrics_collector.conf | 2 + 4.1/amazonlinux/Dockerfile | 308 +++++++++++++++++ 4.1/amazonlinux/docker-entrypoint.sh | 50 +++ 4.1/amazonlinux/management/Dockerfile | 38 +++ 4.2/amazonlinux/10-defaults.conf | 12 + ...ement_agent.disable_metrics_collector.conf | 2 + 4.2/amazonlinux/Dockerfile | 308 +++++++++++++++++ 4.2/amazonlinux/docker-entrypoint.sh | 50 +++ 4.2/amazonlinux/management/Dockerfile | 38 +++ 4.3/amazonlinux/10-defaults.conf | 12 + ...ement_agent.disable_metrics_collector.conf | 2 + 4.3/amazonlinux/Dockerfile | 308 +++++++++++++++++ 4.3/amazonlinux/docker-entrypoint.sh | 50 +++ 4.3/amazonlinux/management/Dockerfile | 38 +++ AGENTS.md | 161 +++++++++ Dockerfile-amazonlinux.template | 318 ++++++++++++++++++ Dockerfile-management.template | 28 +- apply-templates.sh | 2 +- generate-stackbrew-library.sh | 2 +- versions.json | 64 ++++ versions.sh | 51 ++- 27 files changed, 2262 insertions(+), 4 deletions(-) create mode 100644 4.0/amazonlinux/10-defaults.conf create mode 100644 4.0/amazonlinux/20-management_agent.disable_metrics_collector.conf create mode 100644 4.0/amazonlinux/Dockerfile create mode 100755 4.0/amazonlinux/docker-entrypoint.sh create mode 100644 4.0/amazonlinux/management/Dockerfile create mode 100644 4.1/amazonlinux/10-defaults.conf create mode 100644 4.1/amazonlinux/20-management_agent.disable_metrics_collector.conf create mode 100644 4.1/amazonlinux/Dockerfile create mode 100755 4.1/amazonlinux/docker-entrypoint.sh create mode 100644 4.1/amazonlinux/management/Dockerfile create mode 100644 4.2/amazonlinux/10-defaults.conf create mode 100644 4.2/amazonlinux/20-management_agent.disable_metrics_collector.conf create mode 100644 4.2/amazonlinux/Dockerfile create mode 100755 4.2/amazonlinux/docker-entrypoint.sh create mode 100644 4.2/amazonlinux/management/Dockerfile create mode 100644 4.3/amazonlinux/10-defaults.conf create mode 100644 4.3/amazonlinux/20-management_agent.disable_metrics_collector.conf create mode 100644 4.3/amazonlinux/Dockerfile create mode 100755 4.3/amazonlinux/docker-entrypoint.sh create mode 100644 4.3/amazonlinux/management/Dockerfile create mode 100644 AGENTS.md create mode 100644 Dockerfile-amazonlinux.template diff --git a/4.0/amazonlinux/10-defaults.conf b/4.0/amazonlinux/10-defaults.conf new file mode 100644 index 00000000..27973c74 --- /dev/null +++ b/4.0/amazonlinux/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/amazonlinux/20-management_agent.disable_metrics_collector.conf b/4.0/amazonlinux/20-management_agent.disable_metrics_collector.conf new file mode 100644 index 00000000..6eb7a86c --- /dev/null +++ b/4.0/amazonlinux/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/amazonlinux/Dockerfile b/4.0/amazonlinux/Dockerfile new file mode 100644 index 00000000..ef118560 --- /dev/null +++ b/4.0/amazonlinux/Dockerfile @@ -0,0 +1,308 @@ +# syntax=docker/dockerfile:1 +# check=skip=SecretsUsedInArgOrEnv +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +# vim:noet: +FROM amazonlinux:2023 AS build-base + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +RUN set -eux; \ + dnf install -y \ + gcc \ + gcc-c++ \ + make \ + autoconf \ + ncurses-devel \ + wget \ + tar \ + gzip \ + perl \ + findutils \ + ; \ + dnf clean all + +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/amazonlinux +# For context, see https://github.com/docker-library/official-images/issues/4252 + +ENV OPENSSL_VERSION=3.5.7 +ENV OPENSSL_SOURCE_SHA256="a8c0d28a529ca480f9f36cf5792e2cd21984552a3c8e4aa11a24aa31aeac98e8" +# https://www.openssl.org/source/ +ENV OPENSSL_PGP_KEY_IDS="0xBA5473A2B0587B07FB27CF2D216094DFD0CB81EF" + +ENV OTP_VERSION=27.3.4.16 +# 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="b945362f125ecdba4281723595f08716808bafd9137ad153f12e1db917ce8517" + +# 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 +# gnupg2: Required to verify OpenSSL artefacts (--allowerasing replaces gnupg2-minimal) +# ncurses-devel: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli +RUN set -eux; \ + dnf install -y --allowerasing gnupg2; \ + \ + 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"; \ +# OpenSSL's "config" script uses a lot of "uname"-based target detection... + arch="$(uname -m)"; \ + case "$arch" in \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L860 (look for "linux-" and "linux64-" keys) + x86_64) opensslMachine='linux-x86_64' ;; \ + aarch64) opensslMachine='linux-aarch64' ;; \ + *) echo >&2 "error: unsupported arch: '$arch'"; 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" \ + ; \ +# 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 Amazon Linux's CA certificates + rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ + ln -sf /etc/ssl/certs /etc/pki/tls/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"; \ + export CFLAGS='-g -O2'; \ +# 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"; \ + arch="$(uname -m)"; \ +# JIT is only supported on amd64 + arm64; https://github.com/erlang/otp/blob/OTP-25.3.2.2/erts/configure#L24306-L24347 + jitFlag=; \ + case "$arch" in \ + x86_64 | aarch64) jitFlag='--enable-jit' ;; \ + esac; \ + ./configure \ + --prefix="$ERLANG_INSTALL_PATH_PREFIX" \ + --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 amazonlinux:2023 + +# 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/pki/tls/private "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# 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 + dnf install -y shadow-utils hostname procps-ng; \ + 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; \ + dnf install -y --allowerasing wget tar xz findutils gnupg2; \ + \ +# Install gosu for easy step-down from root (not packaged in Amazon Linux) + arch="$(uname -m)"; \ + case "$arch" in \ + 'x86_64') gosuUrl='https://github.com/tianon/gosu/releases/download/1.19/gosu-amd64'; gosuSha256='52c8749d0142edd234e9d6bd5237dff2d81e71f43537e2f4f66f75dd4b243dd0' ;; \ + 'aarch64') gosuUrl='https://github.com/tianon/gosu/releases/download/1.19/gosu-arm64'; gosuSha256='3a8ef022d82c0bc4a98bcb144e77da714c25fcfa64dccc57f6aba7ae47ff1a44' ;; \ + *) echo >&2 "error: unsupported gosu arch: '$arch'"; exit 1 ;; \ + esac; \ + wget --progress dot:giga --output-document /usr/local/bin/gosu "$gosuUrl"; \ + echo "$gosuSha256 */usr/local/bin/gosu" | sha256sum --check --strict -; \ + chmod +x /usr/local/bin/gosu; \ + gosu --version; \ + gosu nobody true; \ + \ + 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"; \ + \ + dnf remove -y wget xz; \ + dnf clean all; \ + \ +# 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 +ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 + +# the rabbitmq-server startup script uses RUNNING_UNDER_SYSTEMD to determine if the erl command +# should be started via exec, which results in beam.smp becoming PID 1 in the container +ENV RUNNING_UNDER_SYSTEMD=true + +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/amazonlinux/docker-entrypoint.sh b/4.0/amazonlinux/docker-entrypoint.sh new file mode 100755 index 00000000..c1c55b6d --- /dev/null +++ b/4.0/amazonlinux/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/amazonlinux/management/Dockerfile b/4.0/amazonlinux/management/Dockerfile new file mode 100644 index 00000000..0b121f3b --- /dev/null +++ b/4.0/amazonlinux/management/Dockerfile @@ -0,0 +1,38 @@ +# syntax=docker/dockerfile:1 +# check=skip=SecretsUsedInArgOrEnv +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +# vim:noet: + +FROM rabbitmq:4.0-amazonlinux + +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 + +RUN set -eux; \ + arch="$(uname -m)"; \ + \ + case "$arch" in \ + 'x86_64') url='https://github.com/rabbitmq/rabbitmqadmin-ng/releases/download/v2.32.0/rabbitmqadmin-2.32.0-x86_64-unknown-linux-gnu'; digest='32d5914481725a6707d164e42298a70906a289fdc5afeca92066106d32a68aee' ;; \ + 'aarch64') url='https://github.com/rabbitmq/rabbitmqadmin-ng/releases/download/v2.32.0/rabbitmqadmin-2.32.0-aarch64-unknown-linux-gnu'; digest='bffb785e3b5f19169a872192aae066b5c8266b3eaf616e6644d2130ee4e972f7' ;; \ + *) echo "[INFO] rabbitmqadmin is not available on $arch (yet?)"; exit 0 ;; \ + esac; \ + \ + dnf install -y wget; \ + \ + wget -O /usr/local/bin/rabbitmqadmin "$url"; \ + echo "$digest */usr/local/bin/rabbitmqadmin" | sha256sum --strict --check -; \ + \ + dnf remove -y wget; \ + dnf clean all; \ + \ + chmod +x /usr/local/bin/rabbitmqadmin; \ + rabbitmqadmin --help + +EXPOSE 15671 15672 diff --git a/4.1/amazonlinux/10-defaults.conf b/4.1/amazonlinux/10-defaults.conf new file mode 100644 index 00000000..27973c74 --- /dev/null +++ b/4.1/amazonlinux/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/amazonlinux/20-management_agent.disable_metrics_collector.conf b/4.1/amazonlinux/20-management_agent.disable_metrics_collector.conf new file mode 100644 index 00000000..6eb7a86c --- /dev/null +++ b/4.1/amazonlinux/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/amazonlinux/Dockerfile b/4.1/amazonlinux/Dockerfile new file mode 100644 index 00000000..41aa69e9 --- /dev/null +++ b/4.1/amazonlinux/Dockerfile @@ -0,0 +1,308 @@ +# syntax=docker/dockerfile:1 +# check=skip=SecretsUsedInArgOrEnv +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +# vim:noet: +FROM amazonlinux:2023 AS build-base + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +RUN set -eux; \ + dnf install -y \ + gcc \ + gcc-c++ \ + make \ + autoconf \ + ncurses-devel \ + wget \ + tar \ + gzip \ + perl \ + findutils \ + ; \ + dnf clean all + +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/amazonlinux +# For context, see https://github.com/docker-library/official-images/issues/4252 + +ENV OPENSSL_VERSION=3.5.7 +ENV OPENSSL_SOURCE_SHA256="a8c0d28a529ca480f9f36cf5792e2cd21984552a3c8e4aa11a24aa31aeac98e8" +# https://www.openssl.org/source/ +ENV OPENSSL_PGP_KEY_IDS="0xBA5473A2B0587B07FB27CF2D216094DFD0CB81EF" + +ENV OTP_VERSION=27.3.4.16 +# 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="b945362f125ecdba4281723595f08716808bafd9137ad153f12e1db917ce8517" + +# 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 +# gnupg2: Required to verify OpenSSL artefacts (--allowerasing replaces gnupg2-minimal) +# ncurses-devel: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli +RUN set -eux; \ + dnf install -y --allowerasing gnupg2; \ + \ + 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"; \ +# OpenSSL's "config" script uses a lot of "uname"-based target detection... + arch="$(uname -m)"; \ + case "$arch" in \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L860 (look for "linux-" and "linux64-" keys) + x86_64) opensslMachine='linux-x86_64' ;; \ + aarch64) opensslMachine='linux-aarch64' ;; \ + *) echo >&2 "error: unsupported arch: '$arch'"; 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" \ + ; \ +# 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 Amazon Linux's CA certificates + rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ + ln -sf /etc/ssl/certs /etc/pki/tls/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"; \ + export CFLAGS='-g -O2'; \ +# 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"; \ + arch="$(uname -m)"; \ +# JIT is only supported on amd64 + arm64; https://github.com/erlang/otp/blob/OTP-25.3.2.2/erts/configure#L24306-L24347 + jitFlag=; \ + case "$arch" in \ + x86_64 | aarch64) jitFlag='--enable-jit' ;; \ + esac; \ + ./configure \ + --prefix="$ERLANG_INSTALL_PATH_PREFIX" \ + --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 amazonlinux:2023 + +# 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/pki/tls/private "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# 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 + dnf install -y shadow-utils hostname procps-ng; \ + 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.8 +# 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; \ + dnf install -y --allowerasing wget tar xz findutils gnupg2; \ + \ +# Install gosu for easy step-down from root (not packaged in Amazon Linux) + arch="$(uname -m)"; \ + case "$arch" in \ + 'x86_64') gosuUrl='https://github.com/tianon/gosu/releases/download/1.19/gosu-amd64'; gosuSha256='52c8749d0142edd234e9d6bd5237dff2d81e71f43537e2f4f66f75dd4b243dd0' ;; \ + 'aarch64') gosuUrl='https://github.com/tianon/gosu/releases/download/1.19/gosu-arm64'; gosuSha256='3a8ef022d82c0bc4a98bcb144e77da714c25fcfa64dccc57f6aba7ae47ff1a44' ;; \ + *) echo >&2 "error: unsupported gosu arch: '$arch'"; exit 1 ;; \ + esac; \ + wget --progress dot:giga --output-document /usr/local/bin/gosu "$gosuUrl"; \ + echo "$gosuSha256 */usr/local/bin/gosu" | sha256sum --check --strict -; \ + chmod +x /usr/local/bin/gosu; \ + gosu --version; \ + gosu nobody true; \ + \ + 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"; \ + \ + dnf remove -y wget xz; \ + dnf clean all; \ + \ +# 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 +ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 + +# the rabbitmq-server startup script uses RUNNING_UNDER_SYSTEMD to determine if the erl command +# should be started via exec, which results in beam.smp becoming PID 1 in the container +ENV RUNNING_UNDER_SYSTEMD=true + +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/amazonlinux/docker-entrypoint.sh b/4.1/amazonlinux/docker-entrypoint.sh new file mode 100755 index 00000000..c1c55b6d --- /dev/null +++ b/4.1/amazonlinux/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/amazonlinux/management/Dockerfile b/4.1/amazonlinux/management/Dockerfile new file mode 100644 index 00000000..05a4eec6 --- /dev/null +++ b/4.1/amazonlinux/management/Dockerfile @@ -0,0 +1,38 @@ +# syntax=docker/dockerfile:1 +# check=skip=SecretsUsedInArgOrEnv +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +# vim:noet: + +FROM rabbitmq:4.1-amazonlinux + +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 + +RUN set -eux; \ + arch="$(uname -m)"; \ + \ + case "$arch" in \ + 'x86_64') url='https://github.com/rabbitmq/rabbitmqadmin-ng/releases/download/v2.32.0/rabbitmqadmin-2.32.0-x86_64-unknown-linux-gnu'; digest='32d5914481725a6707d164e42298a70906a289fdc5afeca92066106d32a68aee' ;; \ + 'aarch64') url='https://github.com/rabbitmq/rabbitmqadmin-ng/releases/download/v2.32.0/rabbitmqadmin-2.32.0-aarch64-unknown-linux-gnu'; digest='bffb785e3b5f19169a872192aae066b5c8266b3eaf616e6644d2130ee4e972f7' ;; \ + *) echo "[INFO] rabbitmqadmin is not available on $arch (yet?)"; exit 0 ;; \ + esac; \ + \ + dnf install -y wget; \ + \ + wget -O /usr/local/bin/rabbitmqadmin "$url"; \ + echo "$digest */usr/local/bin/rabbitmqadmin" | sha256sum --strict --check -; \ + \ + dnf remove -y wget; \ + dnf clean all; \ + \ + chmod +x /usr/local/bin/rabbitmqadmin; \ + rabbitmqadmin --help + +EXPOSE 15671 15672 diff --git a/4.2/amazonlinux/10-defaults.conf b/4.2/amazonlinux/10-defaults.conf new file mode 100644 index 00000000..27973c74 --- /dev/null +++ b/4.2/amazonlinux/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/amazonlinux/20-management_agent.disable_metrics_collector.conf b/4.2/amazonlinux/20-management_agent.disable_metrics_collector.conf new file mode 100644 index 00000000..6eb7a86c --- /dev/null +++ b/4.2/amazonlinux/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/amazonlinux/Dockerfile b/4.2/amazonlinux/Dockerfile new file mode 100644 index 00000000..f5f6e4e3 --- /dev/null +++ b/4.2/amazonlinux/Dockerfile @@ -0,0 +1,308 @@ +# syntax=docker/dockerfile:1 +# check=skip=SecretsUsedInArgOrEnv +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +# vim:noet: +FROM amazonlinux:2023 AS build-base + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +RUN set -eux; \ + dnf install -y \ + gcc \ + gcc-c++ \ + make \ + autoconf \ + ncurses-devel \ + wget \ + tar \ + gzip \ + perl \ + findutils \ + ; \ + dnf clean all + +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 --build-arg PGP_KEYSERVER=pgpkeys.eu 4.2/amazonlinux +# For context, see https://github.com/docker-library/official-images/issues/4252 + +ENV OPENSSL_VERSION=3.5.7 +ENV OPENSSL_SOURCE_SHA256="a8c0d28a529ca480f9f36cf5792e2cd21984552a3c8e4aa11a24aa31aeac98e8" +# https://www.openssl.org/source/ +ENV OPENSSL_PGP_KEY_IDS="0xBA5473A2B0587B07FB27CF2D216094DFD0CB81EF" + +ENV OTP_VERSION=27.3.4.16 +# 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="b945362f125ecdba4281723595f08716808bafd9137ad153f12e1db917ce8517" + +# 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 +# gnupg2: Required to verify OpenSSL artefacts (--allowerasing replaces gnupg2-minimal) +# ncurses-devel: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli +RUN set -eux; \ + dnf install -y --allowerasing gnupg2; \ + \ + 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"; \ +# OpenSSL's "config" script uses a lot of "uname"-based target detection... + arch="$(uname -m)"; \ + case "$arch" in \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L860 (look for "linux-" and "linux64-" keys) + x86_64) opensslMachine='linux-x86_64' ;; \ + aarch64) opensslMachine='linux-aarch64' ;; \ + *) echo >&2 "error: unsupported arch: '$arch'"; 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" \ + ; \ +# 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 Amazon Linux's CA certificates + rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ + ln -sf /etc/ssl/certs /etc/pki/tls/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"; \ + export CFLAGS='-g -O2'; \ +# 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"; \ + arch="$(uname -m)"; \ +# JIT is only supported on amd64 + arm64; https://github.com/erlang/otp/blob/OTP-25.3.2.2/erts/configure#L24306-L24347 + jitFlag=; \ + case "$arch" in \ + x86_64 | aarch64) jitFlag='--enable-jit' ;; \ + esac; \ + ./configure \ + --prefix="$ERLANG_INSTALL_PATH_PREFIX" \ + --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 amazonlinux:2023 + +# 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/pki/tls/private "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# 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 + dnf install -y shadow-utils hostname procps-ng; \ + 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.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; \ + dnf install -y --allowerasing wget tar xz findutils gnupg2; \ + \ +# Install gosu for easy step-down from root (not packaged in Amazon Linux) + arch="$(uname -m)"; \ + case "$arch" in \ + 'x86_64') gosuUrl='https://github.com/tianon/gosu/releases/download/1.19/gosu-amd64'; gosuSha256='52c8749d0142edd234e9d6bd5237dff2d81e71f43537e2f4f66f75dd4b243dd0' ;; \ + 'aarch64') gosuUrl='https://github.com/tianon/gosu/releases/download/1.19/gosu-arm64'; gosuSha256='3a8ef022d82c0bc4a98bcb144e77da714c25fcfa64dccc57f6aba7ae47ff1a44' ;; \ + *) echo >&2 "error: unsupported gosu arch: '$arch'"; exit 1 ;; \ + esac; \ + wget --progress dot:giga --output-document /usr/local/bin/gosu "$gosuUrl"; \ + echo "$gosuSha256 */usr/local/bin/gosu" | sha256sum --check --strict -; \ + chmod +x /usr/local/bin/gosu; \ + gosu --version; \ + gosu nobody true; \ + \ + 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"; \ + \ + dnf remove -y wget xz; \ + dnf clean all; \ + \ +# 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 +ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 + +# the rabbitmq-server startup script uses RUNNING_UNDER_SYSTEMD to determine if the erl command +# should be started via exec, which results in beam.smp becoming PID 1 in the container +ENV RUNNING_UNDER_SYSTEMD=true + +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/amazonlinux/docker-entrypoint.sh b/4.2/amazonlinux/docker-entrypoint.sh new file mode 100755 index 00000000..c1c55b6d --- /dev/null +++ b/4.2/amazonlinux/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/amazonlinux/management/Dockerfile b/4.2/amazonlinux/management/Dockerfile new file mode 100644 index 00000000..df0d3eb2 --- /dev/null +++ b/4.2/amazonlinux/management/Dockerfile @@ -0,0 +1,38 @@ +# syntax=docker/dockerfile:1 +# check=skip=SecretsUsedInArgOrEnv +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +# vim:noet: + +FROM rabbitmq:4.2-amazonlinux + +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 + +RUN set -eux; \ + arch="$(uname -m)"; \ + \ + case "$arch" in \ + 'x86_64') url='https://github.com/rabbitmq/rabbitmqadmin-ng/releases/download/v2.32.0/rabbitmqadmin-2.32.0-x86_64-unknown-linux-gnu'; digest='32d5914481725a6707d164e42298a70906a289fdc5afeca92066106d32a68aee' ;; \ + 'aarch64') url='https://github.com/rabbitmq/rabbitmqadmin-ng/releases/download/v2.32.0/rabbitmqadmin-2.32.0-aarch64-unknown-linux-gnu'; digest='bffb785e3b5f19169a872192aae066b5c8266b3eaf616e6644d2130ee4e972f7' ;; \ + *) echo "[INFO] rabbitmqadmin is not available on $arch (yet?)"; exit 0 ;; \ + esac; \ + \ + dnf install -y wget; \ + \ + wget -O /usr/local/bin/rabbitmqadmin "$url"; \ + echo "$digest */usr/local/bin/rabbitmqadmin" | sha256sum --strict --check -; \ + \ + dnf remove -y wget; \ + dnf clean all; \ + \ + chmod +x /usr/local/bin/rabbitmqadmin; \ + rabbitmqadmin --help + +EXPOSE 15671 15672 diff --git a/4.3/amazonlinux/10-defaults.conf b/4.3/amazonlinux/10-defaults.conf new file mode 100644 index 00000000..27973c74 --- /dev/null +++ b/4.3/amazonlinux/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.3/amazonlinux/20-management_agent.disable_metrics_collector.conf b/4.3/amazonlinux/20-management_agent.disable_metrics_collector.conf new file mode 100644 index 00000000..6eb7a86c --- /dev/null +++ b/4.3/amazonlinux/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.3/amazonlinux/Dockerfile b/4.3/amazonlinux/Dockerfile new file mode 100644 index 00000000..ec333a46 --- /dev/null +++ b/4.3/amazonlinux/Dockerfile @@ -0,0 +1,308 @@ +# syntax=docker/dockerfile:1 +# check=skip=SecretsUsedInArgOrEnv +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +# vim:noet: +FROM amazonlinux:2023 AS build-base + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +RUN set -eux; \ + dnf install -y \ + gcc \ + gcc-c++ \ + make \ + autoconf \ + ncurses-devel \ + wget \ + tar \ + gzip \ + perl \ + findutils \ + ; \ + dnf clean all + +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.3 --build-arg PGP_KEYSERVER=pgpkeys.eu 4.3/amazonlinux +# For context, see https://github.com/docker-library/official-images/issues/4252 + +ENV OPENSSL_VERSION=3.5.7 +ENV OPENSSL_SOURCE_SHA256="a8c0d28a529ca480f9f36cf5792e2cd21984552a3c8e4aa11a24aa31aeac98e8" +# https://www.openssl.org/source/ +ENV OPENSSL_PGP_KEY_IDS="0xBA5473A2B0587B07FB27CF2D216094DFD0CB81EF" + +ENV OTP_VERSION=27.3.4.16 +# 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="b945362f125ecdba4281723595f08716808bafd9137ad153f12e1db917ce8517" + +# 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 +# gnupg2: Required to verify OpenSSL artefacts (--allowerasing replaces gnupg2-minimal) +# ncurses-devel: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli +RUN set -eux; \ + dnf install -y --allowerasing gnupg2; \ + \ + 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"; \ +# OpenSSL's "config" script uses a lot of "uname"-based target detection... + arch="$(uname -m)"; \ + case "$arch" in \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L860 (look for "linux-" and "linux64-" keys) + x86_64) opensslMachine='linux-x86_64' ;; \ + aarch64) opensslMachine='linux-aarch64' ;; \ + *) echo >&2 "error: unsupported arch: '$arch'"; 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" \ + ; \ +# 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 Amazon Linux's CA certificates + rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ + ln -sf /etc/ssl/certs /etc/pki/tls/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"; \ + export CFLAGS='-g -O2'; \ +# 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"; \ + arch="$(uname -m)"; \ +# JIT is only supported on amd64 + arm64; https://github.com/erlang/otp/blob/OTP-25.3.2.2/erts/configure#L24306-L24347 + jitFlag=; \ + case "$arch" in \ + x86_64 | aarch64) jitFlag='--enable-jit' ;; \ + esac; \ + ./configure \ + --prefix="$ERLANG_INSTALL_PATH_PREFIX" \ + --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 amazonlinux:2023 + +# 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/pki/tls/private "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# 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 + dnf install -y shadow-utils hostname procps-ng; \ + 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.3.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; \ + dnf install -y --allowerasing wget tar xz findutils gnupg2; \ + \ +# Install gosu for easy step-down from root (not packaged in Amazon Linux) + arch="$(uname -m)"; \ + case "$arch" in \ + 'x86_64') gosuUrl='https://github.com/tianon/gosu/releases/download/1.19/gosu-amd64'; gosuSha256='52c8749d0142edd234e9d6bd5237dff2d81e71f43537e2f4f66f75dd4b243dd0' ;; \ + 'aarch64') gosuUrl='https://github.com/tianon/gosu/releases/download/1.19/gosu-arm64'; gosuSha256='3a8ef022d82c0bc4a98bcb144e77da714c25fcfa64dccc57f6aba7ae47ff1a44' ;; \ + *) echo >&2 "error: unsupported gosu arch: '$arch'"; exit 1 ;; \ + esac; \ + wget --progress dot:giga --output-document /usr/local/bin/gosu "$gosuUrl"; \ + echo "$gosuSha256 */usr/local/bin/gosu" | sha256sum --check --strict -; \ + chmod +x /usr/local/bin/gosu; \ + gosu --version; \ + gosu nobody true; \ + \ + 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"; \ + \ + dnf remove -y wget xz; \ + dnf clean all; \ + \ +# 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 +ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 + +# the rabbitmq-server startup script uses RUNNING_UNDER_SYSTEMD to determine if the erl command +# should be started via exec, which results in beam.smp becoming PID 1 in the container +ENV RUNNING_UNDER_SYSTEMD=true + +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.3/amazonlinux/docker-entrypoint.sh b/4.3/amazonlinux/docker-entrypoint.sh new file mode 100755 index 00000000..c1c55b6d --- /dev/null +++ b/4.3/amazonlinux/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.3/amazonlinux/management/Dockerfile b/4.3/amazonlinux/management/Dockerfile new file mode 100644 index 00000000..17f3660d --- /dev/null +++ b/4.3/amazonlinux/management/Dockerfile @@ -0,0 +1,38 @@ +# syntax=docker/dockerfile:1 +# check=skip=SecretsUsedInArgOrEnv +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +# vim:noet: + +FROM rabbitmq:4.3-amazonlinux + +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 + +RUN set -eux; \ + arch="$(uname -m)"; \ + \ + case "$arch" in \ + 'x86_64') url='https://github.com/rabbitmq/rabbitmqadmin-ng/releases/download/v2.32.0/rabbitmqadmin-2.32.0-x86_64-unknown-linux-gnu'; digest='32d5914481725a6707d164e42298a70906a289fdc5afeca92066106d32a68aee' ;; \ + 'aarch64') url='https://github.com/rabbitmq/rabbitmqadmin-ng/releases/download/v2.32.0/rabbitmqadmin-2.32.0-aarch64-unknown-linux-gnu'; digest='bffb785e3b5f19169a872192aae066b5c8266b3eaf616e6644d2130ee4e972f7' ;; \ + *) echo "[INFO] rabbitmqadmin is not available on $arch (yet?)"; exit 0 ;; \ + esac; \ + \ + dnf install -y wget; \ + \ + wget -O /usr/local/bin/rabbitmqadmin "$url"; \ + echo "$digest */usr/local/bin/rabbitmqadmin" | sha256sum --strict --check -; \ + \ + dnf remove -y wget; \ + dnf clean all; \ + \ + chmod +x /usr/local/bin/rabbitmqadmin; \ + rabbitmqadmin --help + +EXPOSE 15671 15672 diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..07af327f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,161 @@ +# Agent guide: docker-library/rabbitmq + +Orientation for an AI working in this repo. It documents how the repo is +*mechanically* built and the traps that are not obvious from the source. It does +not cover maintainer intent or PR conventions — those belong to the +docker-library maintainers. + +## What this repo is + +The source for the [`rabbitmq` Docker Official Image](https://hub.docker.com/_/rabbitmq/). +It does not build one Dockerfile per hand — it *generates* a matrix of +Dockerfiles (RabbitMQ version × OS variant × management sub-variant) from a +small set of templates. + +`README.md` is a generated stub for Docker Hub users; it documents nothing about +working in the repo. The real "source of truth" manifest that Docker Hub +consumes lives downstream in +[`docker-library/official-images`](https://github.com/docker-library/official-images) +as `library/rabbitmq`, produced by this repo's `generate-stackbrew-library.sh`. + +## The golden rule + +**Never edit the generated `4.x//` files directly.** They carry a +`# NOTE: THIS DOCKERFILE IS GENERATED ... PLEASE DO NOT EDIT IT DIRECTLY` header +and are overwritten on every regeneration. + +Edit the *inputs*, then regenerate: + +- Version/pin data → `versions.json` (and `versions.sh`, which produces it). +- Dockerfile content → `Dockerfile-.template` and + `Dockerfile-management.template`. +- Then run `./apply-templates.sh` and commit the regenerated `4.x/` output + together with your template change. + +CI enforces this. `.github/workflows/verify-templating.yml` runs +`./apply-templates.sh` then `git diff --exit-code` — if the committed generated +files don't match what the templates produce, the build fails. + +## The generation pipeline + +- `versions.sh [version...]` — fetches upstream versions (RabbitMQ, Erlang/OTP, + OpenSSL, gosu, rabbitmqadmin) and writes pinned versions + SHA256s into + `versions.json`. Two distinct kinds of pin live in associative arrays at the + top, keyed by RabbitMQ minor line — do not confuse them: + - **OS base-image versions**: `alpineVersions`, `ubuntuVersions`, + `amazonlinuxVersions` (e.g. `[4.3]='2023'`). Edit these to change the OS a + variant builds on. + - **Toolchain major versions** (not OS versions): `otpMajors` (Erlang/OTP + major, "Maximum supported Erlang/OTP") and `opensslMajors` (OpenSSL major). + `versions.sh` resolves each to the latest matching upstream release. +- `apply-templates.sh [version...]` — renders each `Dockerfile-.template` + through jq-template (`.jq-template.awk`, a gawk script) into + `4.x//Dockerfile` and `4.x//management/Dockerfile`, and + copies `docker-entrypoint.sh` + `conf.d/*.conf` in. Requires `versions.json` + to exist first. +- `update.sh [version...]` — the canonical wrapper: runs `versions.sh` then + `apply-templates.sh`. +- `generate-stackbrew-library.sh` — emits the official-images manifest (tags + + architectures + git commit + directory) to stdout. + +Templates are jq-template: `{{ ... }}` blocks are jq expressions with repo data +(`.version`, `.openssl`, `.otp`, `env.variant`, etc.) in scope. A trailing `-` +inside a block (`{{ ... -}}`) trims following whitespace. + +## Adding or changing an OS variant + +A variant named `X` needs, consistently: + +1. A version entry in `versions.sh` — an `XVersions` associative array plus its + export and its `X: { version: env.XVersion }` entry in the `jq` that builds + `versions.json`. Run `./versions.sh` to populate `versions.json`. +2. `Dockerfile-X.template` — the multi-stage build for that base image. +3. `X` added to the variant loop in **both** `apply-templates.sh` and + `generate-stackbrew-library.sh` (the two lists must agree). +4. A branch in `Dockerfile-management.template`'s `if env.variant == ...` chain + for how that base installs `rabbitmqadmin`. +5. `./apply-templates.sh`, then commit the regenerated `4.x/X/` dirs. + +Notes that bit us and will bite again: + +- **`defaultVariant='ubuntu'`** in `generate-stackbrew-library.sh`. The default + variant's tags are *untagged* (`4.3`, not `4.3-ubuntu`); every other variant + is suffixed (`4.3-`). `Dockerfile-management.template`'s `FROM` relies + on this — the base image reference is untagged only for ubuntu. +- **Alpine swaps `gosu` for `su-exec`** via a `sed 's/gosu/su-exec/g'` on the + copied `docker-entrypoint.sh`, applied only when `variant = alpine` in + `apply-templates.sh`. Other variants keep `gosu`. +- The generated dirs are marked `linguist-generated` in `.gitattributes`. + +## OS-specific gotchas (Amazon Linux 2023 / `dnf`) + +Verified while adding the amazonlinux variant; not obvious and cost real build +iterations: + +- AL2023 ships **`-minimal`** packages that *conflict* with their full versions. + `gnupg2-minimal` lacks `dirmngr` (needed for `gpg --keyserver ... --recv-keys`), + so install the full package with `dnf install -y --allowerasing gnupg2`. The + base already provides the `curl` binary via `curl-minimal`; installing full + `curl` conflicts — omit it rather than install it. +- The AL2023 base is minimal — many tools ubuntu's base ships are absent and + must be installed explicitly. Distinguish three categories, because they belong + in different build stages and have different cleanup rules: + - **Build-time toolchain** (builder stages only, never the final stage): + `gcc gcc-c++ make autoconf ncurses-devel`. + - **Transient fetch/verify tools** (install then remove in the same final RUN): + `wget`, `xz`. See the runtime-parity rule below. + - **Genuine runtime dependencies** (install and keep in the final stage): + `findutils` (`docker-entrypoint.sh` runs `find` at container start — AL2023 + has no `find` by default, whereas ubuntu's base does), `hostname` (the + entrypoint calls `hostname`/`hostname -s`), `procps-ng` (for `ps`), + `shadow-utils` (for the build-time `groupadd`/`useradd`; not removable + without a `dnf clean all`, so left installed), and `tar`. +- **Runtime parity with ubuntu is the rule for what stays installed.** The + amazonlinux final image should expose the same runtime toolset as the shipped + ubuntu image. Verified against `rabbitmq:4.3`: ubuntu keeps `tar`, `find`, + `gosu`, `hostname`, `ps` and purges `wget` + `xz`. So the amazonlinux cleanup + is `dnf remove -y wget xz; dnf clean all` — **not** `tar`/`findutils`, which + ubuntu keeps and the entrypoint needs. (To decide a tool's fate, check the + shipped ubuntu image: `docker run --rm rabbitmq: command -v `.) +- `dnf remove` cannot remove **protected** packages: it refuses to remove + `gnupg2` because `dnf` itself depends on it. So the full `gnupg2` (installed + via `--allowerasing` to get `dirmngr`, replacing `gnupg2-minimal`) is stuck in + the final image — the one unavoidable divergence from ubuntu, which purges + `gnupg`. A `dnf remove` list that includes a protected package aborts and + removes *nothing*, so never mix `gnupg2` into the cleanup line. +- Every final-stage `dnf install` must be paired with a `dnf clean all` **in the + same RUN** — a later RUN's clean cannot reclaim an earlier layer's + `/var/cache/dnf`. +- **`gosu` is not packaged.** It is downloaded from the tianon/gosu GitHub + release and verified by SHA256 (pinned in `versions.json`, arch-mapped in the + template). Note `versions.json` uses arch key `arm64` for gosu but `arm64v8` + for rabbitmqadmin — the two `def uname_arches` maps in the templates differ + accordingly, so do not copy one map into the other's block. +- Arch detection uses `uname -m` (`x86_64` / `aarch64`) — there is no `dpkg` + (`--print-architecture`) or apk (`--print-arch`). + +## Validating locally + +- **Build a variant for real** before trusting a change (each compiles OpenSSL + + Erlang/OTP from source, so it's slow). The management sub-variant `FROM`s the + base image by the exact tag `generate-stackbrew-library.sh` would publish, so + tag the base you build to match, or the management build won't find it: + - Non-default variant (e.g. amazonlinux, alpine) — the base tag is suffixed: + ``` + docker build -t rabbitmq:4.3-amazonlinux 4.3/amazonlinux + docker build -t rabbitmq:4.3-management-amazonlinux 4.3/amazonlinux/management + ``` + - Default variant (ubuntu) — the base tag is **untagged** (see `defaultVariant` + above), so its management image `FROM`s `rabbitmq:4.3`, not + `rabbitmq:4.3-ubuntu`: + ``` + docker build -t rabbitmq:4.3 4.3/ubuntu + docker build -t rabbitmq:4.3-management 4.3/ubuntu/management + ``` +- **Check the downstream manifest gate.** The acceptance checks that gate the + official-images PR are `naughty-from.sh`, `naughty-sharedtags.sh`, and + `naughty-constraints.sh` in the official-images repo, run via `bashbrew`. A + base image referenced in `FROM` must itself be an official image supporting + the target architectures, or `naughty-from.sh` rejects it. Generate the + candidate manifest with `./generate-stackbrew-library.sh` and validate it with + a local `bashbrew` build against the official-images `oi/` scripts. diff --git a/Dockerfile-amazonlinux.template b/Dockerfile-amazonlinux.template new file mode 100644 index 00000000..59a6bc81 --- /dev/null +++ b/Dockerfile-amazonlinux.template @@ -0,0 +1,318 @@ +# vim:noet: +FROM amazonlinux:{{ .amazonlinux.version }} AS build-base + +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +RUN set -eux; \ + dnf install -y \ + gcc \ + gcc-c++ \ + make \ + autoconf \ + ncurses-devel \ + wget \ + tar \ + gzip \ + perl \ + findutils \ + ; \ + dnf clean all + +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 }}/amazonlinux +# 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 +# gnupg2: Required to verify OpenSSL artefacts (--allowerasing replaces gnupg2-minimal) +# ncurses-devel: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli +RUN set -eux; \ + dnf install -y --allowerasing gnupg2; \ + \ + 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"; \ +# OpenSSL's "config" script uses a lot of "uname"-based target detection... + arch="$(uname -m)"; \ + case "$arch" in \ +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L860 (look for "linux-" and "linux64-" keys) + x86_64) opensslMachine='linux-x86_64' ;; \ + aarch64) opensslMachine='linux-aarch64' ;; \ + *) echo >&2 "error: unsupported arch: '$arch'"; 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" \ + ; \ +# 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 Amazon Linux's CA certificates + rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ + ln -sf /etc/ssl/certs /etc/pki/tls/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"; \ + export CFLAGS='-g -O2'; \ +# 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"; \ + arch="$(uname -m)"; \ +# JIT is only supported on amd64 + arm64; https://github.com/erlang/otp/blob/OTP-25.3.2.2/erts/configure#L24306-L24347 + jitFlag=; \ + case "$arch" in \ + x86_64 | aarch64) jitFlag='--enable-jit' ;; \ + esac; \ + ./configure \ + --prefix="$ERLANG_INSTALL_PATH_PREFIX" \ + --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 amazonlinux:{{ .amazonlinux.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/pki/tls/private "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ + \ +# 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 + dnf install -y shadow-utils hostname procps-ng; \ + 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; \ + dnf install -y --allowerasing wget tar xz findutils gnupg2; \ + \ +# Install gosu for easy step-down from root (not packaged in Amazon Linux) + arch="$(uname -m)"; \ + case "$arch" in \ +{{ .gosu.arches | to_entries | map( -}} +{{ def uname_arches: { + amd64: "x86_64", + arm64: "aarch64", +} -}} + {{ uname_arches[.key] // empty | @sh }}) gosuUrl={{ .value.url | @sh }}; gosuSha256={{ .value.digest | @sh }} ;; \ +{{ ) | join("") -}} + *) echo >&2 "error: unsupported gosu arch: '$arch'"; exit 1 ;; \ + esac; \ + wget --progress dot:giga --output-document /usr/local/bin/gosu "$gosuUrl"; \ + echo "$gosuSha256 */usr/local/bin/gosu" | sha256sum --check --strict -; \ + chmod +x /usr/local/bin/gosu; \ + gosu --version; \ + gosu nobody true; \ + \ + 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"; \ + \ + dnf remove -y wget xz; \ + dnf clean all; \ + \ +# 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 +ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 + +# the rabbitmq-server startup script uses RUNNING_UNDER_SYSTEMD to determine if the erl command +# should be started via exec, which results in beam.smp becoming PID 1 in the container +ENV RUNNING_UNDER_SYSTEMD=true + +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 index 65d49caa..8db5fa30 100644 --- a/Dockerfile-management.template +++ b/Dockerfile-management.template @@ -1,8 +1,9 @@ # vim:noet: FROM {{ + # "ubuntu" is the default variant, so its base image is untagged (see "defaultVariant" in generate-stackbrew-library.sh) "rabbitmq:" + env.version - + if env.variant == "alpine" then "-alpine" else "" end + + if env.variant == "ubuntu" then "" else "-" + env.variant end }} RUN set -eux; \ @@ -30,6 +31,31 @@ RUN set -eux; \ \ chmod +x /usr/local/bin/rabbitmqadmin; \ rabbitmqadmin --help +{{ ) elif env.variant == "amazonlinux" then ( -}} +RUN set -eux; \ + arch="$(uname -m)"; \ + \ + case "$arch" in \ +{{ .rabbitmqadmin.arches | to_entries | map( -}} +{{ def uname_arches: { + "amd64": "x86_64", + "arm64v8": "aarch64", +} -}} + {{ uname_arches[.key] // empty | @sh }}) url={{ .value.url | @sh }}; digest={{ .value.digest | @sh }} ;; \ +{{ ) | join("") -}} + *) echo "[INFO] rabbitmqadmin is not available on $arch (yet?)"; exit 0 ;; \ + esac; \ + \ + dnf install -y wget; \ + \ + wget -O /usr/local/bin/rabbitmqadmin "$url"; \ + echo "$digest */usr/local/bin/rabbitmqadmin" | sha256sum --strict --check -; \ + \ + dnf remove -y wget; \ + dnf clean all; \ + \ + chmod +x /usr/local/bin/rabbitmqadmin; \ + rabbitmqadmin --help {{ ) else ( -}} RUN set -eux; \ arch="$(dpkg --print-architecture)"; \ diff --git a/apply-templates.sh b/apply-templates.sh index 53a5dd12..6ca56bf3 100755 --- a/apply-templates.sh +++ b/apply-templates.sh @@ -44,7 +44,7 @@ for version; do continue fi - for variant in alpine ubuntu; do + for variant in alpine amazonlinux ubuntu; do export variant echo "processing $version/$variant ..." diff --git a/generate-stackbrew-library.sh b/generate-stackbrew-library.sh index 711b474b..3c557921 100755 --- a/generate-stackbrew-library.sh +++ b/generate-stackbrew-library.sh @@ -118,7 +118,7 @@ for version; do done fi - for variant in ubuntu alpine; do + for variant in ubuntu alpine amazonlinux; do dir="$version/$variant" commit="$(dirCommit "$dir")" diff --git a/versions.json b/versions.json index 4e204236..ef792b91 100644 --- a/versions.json +++ b/versions.json @@ -3,6 +3,22 @@ "alpine": { "version": "3.23" }, + "amazonlinux": { + "version": "2023" + }, + "gosu": { + "arches": { + "amd64": { + "digest": "52c8749d0142edd234e9d6bd5237dff2d81e71f43537e2f4f66f75dd4b243dd0", + "url": "https://github.com/tianon/gosu/releases/download/1.19/gosu-amd64" + }, + "arm64": { + "digest": "3a8ef022d82c0bc4a98bcb144e77da714c25fcfa64dccc57f6aba7ae47ff1a44", + "url": "https://github.com/tianon/gosu/releases/download/1.19/gosu-arm64" + } + }, + "version": "1.19" + }, "openssl": { "sha256": "a8c0d28a529ca480f9f36cf5792e2cd21984552a3c8e4aa11a24aa31aeac98e8", "version": "3.5.7" @@ -42,6 +58,22 @@ "alpine": { "version": "3.23" }, + "amazonlinux": { + "version": "2023" + }, + "gosu": { + "arches": { + "amd64": { + "digest": "52c8749d0142edd234e9d6bd5237dff2d81e71f43537e2f4f66f75dd4b243dd0", + "url": "https://github.com/tianon/gosu/releases/download/1.19/gosu-amd64" + }, + "arm64": { + "digest": "3a8ef022d82c0bc4a98bcb144e77da714c25fcfa64dccc57f6aba7ae47ff1a44", + "url": "https://github.com/tianon/gosu/releases/download/1.19/gosu-arm64" + } + }, + "version": "1.19" + }, "openssl": { "sha256": "a8c0d28a529ca480f9f36cf5792e2cd21984552a3c8e4aa11a24aa31aeac98e8", "version": "3.5.7" @@ -81,6 +113,22 @@ "alpine": { "version": "3.23" }, + "amazonlinux": { + "version": "2023" + }, + "gosu": { + "arches": { + "amd64": { + "digest": "52c8749d0142edd234e9d6bd5237dff2d81e71f43537e2f4f66f75dd4b243dd0", + "url": "https://github.com/tianon/gosu/releases/download/1.19/gosu-amd64" + }, + "arm64": { + "digest": "3a8ef022d82c0bc4a98bcb144e77da714c25fcfa64dccc57f6aba7ae47ff1a44", + "url": "https://github.com/tianon/gosu/releases/download/1.19/gosu-arm64" + } + }, + "version": "1.19" + }, "openssl": { "sha256": "a8c0d28a529ca480f9f36cf5792e2cd21984552a3c8e4aa11a24aa31aeac98e8", "version": "3.5.7" @@ -120,6 +168,22 @@ "alpine": { "version": "3.23" }, + "amazonlinux": { + "version": "2023" + }, + "gosu": { + "arches": { + "amd64": { + "digest": "52c8749d0142edd234e9d6bd5237dff2d81e71f43537e2f4f66f75dd4b243dd0", + "url": "https://github.com/tianon/gosu/releases/download/1.19/gosu-amd64" + }, + "arm64": { + "digest": "3a8ef022d82c0bc4a98bcb144e77da714c25fcfa64dccc57f6aba7ae47ff1a44", + "url": "https://github.com/tianon/gosu/releases/download/1.19/gosu-arm64" + } + }, + "version": "1.19" + }, "openssl": { "sha256": "a8c0d28a529ca480f9f36cf5792e2cd21984552a3c8e4aa11a24aa31aeac98e8", "version": "3.5.7" diff --git a/versions.sh b/versions.sh index e5e71dbd..20b81c6a 100755 --- a/versions.sh +++ b/versions.sh @@ -16,6 +16,13 @@ declare -A ubuntuVersions=( [4.3]='24.04' ) +declare -A amazonlinuxVersions=( + [4.0]='2023' + [4.1]='2023' + [4.2]='2023' + [4.3]='2023' +) + # https://www.rabbitmq.com/which-erlang.html ("Maximum supported Erlang/OTP") declare -A otpMajors=( [4.0]='27' @@ -83,6 +90,41 @@ rabbitmqadmin="$( )" export rabbitmqadmin +gosu="$( + wget --quiet --output-document=- \ + --header='Accept: application/vnd.github+json' \ + --header='X-GitHub-Api-Version: 2022-11-28' \ + https://api.github.com/repos/tianon/gosu/releases/latest \ + | jq -c ' + { + version: (.tag_name | ltrimstr("v")), + arches: ( + .assets + | map({ + key: ( + .name + | first( + ( + [ "^gosu-amd64$", "amd64" ], + [ "^gosu-arm64$", "arm64" ], + empty + ) as [ $regex, $arch ] + | if test($regex) then $arch else empty end + ) + ), + value: { + url: .browser_download_url, + digest: ((.digest // error("gosu \(.name) is missing a sha256 digest")) | ltrimstr("sha256:")), + }, + }) + | sort_by(.key) + | from_entries + ), + } + ' +)" +export gosu + for version in "${versions[@]}"; do export version @@ -198,7 +240,10 @@ for version in "${versions[@]}"; do ubuntuVersion="${ubuntuVersions[$rcVersion]}" export ubuntuVersion - echo "$version: $fullVersion (otp $otpVersion, openssl $opensslVersion, alpine $alpineVersion, ubuntu $ubuntuVersion)" + amazonlinuxVersion="${amazonlinuxVersions[$rcVersion]}" + export amazonlinuxVersion + + echo "$version: $fullVersion (otp $otpVersion, openssl $opensslVersion, alpine $alpineVersion, ubuntu $ubuntuVersion, amazonlinux $amazonlinuxVersion)" json="$( jq <<<"$json" -c ' @@ -218,6 +263,10 @@ for version in "${versions[@]}"; do ubuntu: { version: env.ubuntuVersion }, + amazonlinux: { + version: env.amazonlinuxVersion + }, + gosu: (env.gosu | fromjson), rabbitmqadmin: (env.rabbitmqadmin | fromjson), } '