# The official Canonical Ubuntu Bionic image is ideal from a security perspective, # especially for the enterprises that we, the RabbitMQ team, have to deal with ARG BASE=ubuntu FROM ${BASE}:20.04 RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends \ # grab gosu for easy step-down from root gosu \ ; \ rm -rf /var/lib/apt/lists/*; \ # verify that the "gosu" binary works gosu nobody true # PGP key servers are too flaky for us to verify during every CI triggered build # https://github.com/docker-library/official-images/issues/4252 ARG SKIP_PGP_VERIFY=false # Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally ARG PGP_KEYSERVER=ha.pool.sks-keyservers.net # If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, # run the build with a different PGP_KEYSERVER, e.g. docker build --tag rabbitmq:3.7 --build-arg PGP_KEYSERVER=pgpkeys.eu 3.7/ubuntu # For context, see https://github.com/docker-library/official-images/issues/4252 # Using the latest OpenSSL LTS release, with support until September 2023 - https://www.openssl.org/source/ ENV OPENSSL_VERSION 1.1.1g ENV OPENSSL_SOURCE_SHA256="ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46" # https://www.openssl.org/community/omc.html ENV OPENSSL_PGP_KEY_IDS="0x8657ABB260F056B1E5190839D9C4D26D0E604491 0x5B2545DAB21995F4088CEFAA36CEE4DEB00CFE33 0xED230BEC4D4F2518B9D7DF41F0DB4D21C1D35231 0xC1F33DD8CE1D4CC613AF14DA9195C48241FBF7DD 0x7953AC1FBC3DC8B3B292393ED5E9E43F7DF9EE8C 0xE5E52560DD91C556DDBDA5D02064C53641C25E5D" # Use the latest stable Erlang/OTP release - make find-latest-otp - https://github.com/erlang/otp/tags ARG OTP_VERSION ENV OTP_VERSION ${OTP_VERSION} # TODO add PGP checking when the feature will be added to Erlang/OTP's build system # http://erlang.org/pipermail/erlang-questions/2019-January/097067.html ARG OTP_SHA256 ENV OTP_SOURCE_SHA256=${OTP_SHA256} ARG SKIP_OTP_VERIFY=false # Install dependencies required to build Erlang/OTP from source # https://erlang.org/doc/installation_guide/INSTALL.html # autoconf: Required to configure Erlang/OTP before compiling # dpkg-dev: Required to set up host & build type when compiling Erlang/OTP # gnupg: Required to verify OpenSSL artefacts # libncurses5-dev: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli RUN set -eux; \ \ savedAptMark="$(apt-mark showmanual)"; \ apt-get update; \ apt-get install --yes --no-install-recommends \ autoconf \ ca-certificates \ dpkg-dev \ gcc \ g++ \ gnupg \ libncurses5-dev \ make \ wget \ ; \ rm -rf /var/lib/apt/lists/*; \ \ OPENSSL_SOURCE_URL="https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz"; \ OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ OPENSSL_CONFIG_DIR=/usr/local/etc/ssl; \ \ # 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" || true; \ done; \ test "$SKIP_PGP_VERIFY" == "true" || 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... MACHINE="$(dpkg-architecture --query DEB_BUILD_GNU_CPU)" \ RELEASE="4.x.y-z" \ SYSTEM='Linux' \ BUILD='???' \ ./config \ --openssldir="$OPENSSL_CONFIG_DIR" \ # add -rpath to avoid conflicts between our OpenSSL's "libssl.so" and the libssl package by making sure /usr/local/lib is searched first (but only for Erlang/OpenSSL to avoid issues with other tools using libssl; https://github.com/docker-library/rabbitmq/issues/364) -Wl,-rpath=/usr/local/lib \ ; \ # Compile, install OpenSSL, verify that the command-line works & development headers are present make -j "$(getconf _NPROCESSORS_ONLN)"; \ make install_sw install_ssldirs; \ cd ..; \ rm -rf "$OPENSSL_PATH"*; \ ldconfig; \ # use Debian's CA certificates rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR"; \ # smoke test openssl version; \ \ OTP_SOURCE_URL="https://github.com/erlang/otp/archive/OTP-$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"; \ test "$SKIP_OTP_VERIFY" = "true" || 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"; \ ./otp_build autoconf; \ CFLAGS="$(dpkg-buildflags --get CFLAGS)"; export CFLAGS; \ # add -rpath to avoid conflicts between our OpenSSL's "libssl.so" and the libssl package by making sure /usr/local/lib is searched first (but only for Erlang/OpenSSL to avoid issues with other tools using libssl; https://github.com/docker-library/rabbitmq/issues/364) export CFLAGS="$CFLAGS -Wl,-rpath=/usr/local/lib"; \ hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ ./configure \ --host="$hostArch" \ --build="$buildArch" \ --disable-dynamic-ssl-lib \ --disable-hipe \ --disable-sctp \ --disable-silent-rules \ --enable-jit \ --enable-clock-gettime \ --enable-hybrid-heap \ --enable-kernel-poll \ --enable-shared-zlib \ --enable-smp-support \ --enable-threads \ --with-microstate-accounting=extra \ --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-ssh \ --without-tftp \ --without-wx \ ; \ # Compile & install Erlang/OTP make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ make install; \ cd ..; \ rm -rf \ "$OTP_PATH"* \ /usr/local/lib/erlang/lib/*/examples \ /usr/local/lib/erlang/lib/*/src \ ; \ \ # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies apt-mark auto '.*' > /dev/null; \ [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \ find /usr/local -type f -executable -exec ldd '{}' ';' \ | awk '/=>/ { print $(NF-1) }' \ | sort -u \ | xargs -r dpkg-query --search \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual \ ; \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ \ # Check that OpenSSL still works after purging build dependencies openssl version; \ # Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly erl -noshell -eval 'io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq # Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM RUN set -eux; \ 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 777 "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie # https://www.rabbitmq.com/signatures.html#importing-gpg # ENV RABBITMQ_PGP_KEY_ID="0x0A9AF2115F4687BD29803A206B73A36E6026DFCA" ENV RABBITMQ_HOME=/opt/rabbitmq # Add RabbitMQ to PATH, send all logs to TTY ENV PATH=$RABBITMQ_HOME/sbin:$PATH \ RABBITMQ_LOGS=- RUN set -eux; \ \ savedAptMark="$(apt-mark showmanual)"; \ apt-get update; \ apt-get install --yes --no-install-recommends \ ca-certificates \ gnupg \ wget \ xz-utils \ ; \ rm -rf /var/lib/apt/lists/*; \ \ apt-mark auto '.*' > /dev/null; \ apt-mark manual $savedAptMark; \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false # Install RabbitMQ ARG RABBITMQ_BUILD COPY ${RABBITMQ_BUILD} $RABBITMQ_HOME RUN set -eux; \ # 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"; \ \ # 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" # Added for backwards compatibility - users can simply COPY custom plugins to /plugins RUN ln -sf /opt/rabbitmq/plugins /plugins # set home so that any `--user` knows where to put the erlang cookie ENV HOME $RABBITMQ_DATA_DIR # Hint that the data (a.k.a. home dir) dir should be separate volume VOLUME $RABBITMQ_DATA_DIR # warning: the VM is running with native name encoding of latin1 which may cause Elixir to malfunction as it expects utf8. Please ensure your locale is set to UTF-8 (which can be verified by running "locale" in your shell) # Setting all environment variables that control language preferences, behaviour differs - https://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html#The-LANGUAGE-variable # https://docs.docker.com/samples/library/ubuntu/#locales ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 COPY --chown=rabbitmq:rabbitmq 10-default-guest-user.conf /etc/rabbitmq/conf.d/ COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] # EPMD AMQP-TLS AMQP ERLANG EXPOSE 4369 5671 5672 25672 CMD ["rabbitmq-server"] # rabbitmq_management RUN rabbitmq-plugins enable --offline rabbitmq_management && \ rabbitmq-plugins is_enabled rabbitmq_management --offline # extract "rabbitmqadmin" from inside the "rabbitmq_management-X.Y.Z.ez" plugin zipfile # see https://github.com/docker-library/rabbitmq/issues/207 # RabbitMQ 3.9 onwards uses uncompressed plugins by default, in which case extraction is # unnecesary RUN set -eux; \ if [ -s /plugins/rabbitmq_management-*.ez ]; then \ erl -noinput -eval ' \ { ok, AdminBin } = zip:foldl(fun(FileInArchive, GetInfo, GetBin, Acc) -> \ case Acc of \ "" -> \ case lists:suffix("/rabbitmqadmin", FileInArchive) of \ true -> GetBin(); \ false -> Acc \ end; \ _ -> Acc \ end \ end, "", init:get_plain_arguments()), \ io:format("~s", [ AdminBin ]), \ init:stop(). \ ' -- /plugins/rabbitmq_management-*.ez > /usr/local/bin/rabbitmqadmin; \ else \ cp /plugins/rabbitmq_management-*/priv/www/cli/rabbitmqadmin /usr/local/bin/rabbitmqadmin; \ fi; \ [ -s /usr/local/bin/rabbitmqadmin ]; \ chmod +x /usr/local/bin/rabbitmqadmin; \ apt-get update; apt-get install -y --no-install-recommends python3 dstat sysstat htop nmon tmux neovim; rm -rf /var/lib/apt/lists/*; \ rabbitmqadmin --version # MANAGEMENT-TLS MANAGEMENT EXPOSE 15671 15672 RUN rabbitmq-plugins enable --offline rabbitmq_prometheus && \ rabbitmq-plugins is_enabled rabbitmq_prometheus --offline # PROMETHEUS-TLS PROMETHEUS EXPOSE 15691 15692 RUN rabbitmq-plugins enable --all # STREAM-TLS STREAM EXPOSE 5551 5552 # MQTT-TLS MQTT EXPOSE 8883 1883 # WEB-MQTT-TLS WEB-MQTT EXPOSE 15676 15675 # STOMP-TLS STOMP EXPOSE 61614 61613 # WEB-STOMP-TLS WEB-STOMP EXPOSE 15673 15674 # EXAMPLES EXPOSE 15670