├── .gitattributes ├── .github └── workflows │ ├── ci.yml │ └── verify-templating.yml ├── .gitignore ├── 3.8-rc ├── alpine │ ├── Dockerfile │ ├── docker-entrypoint.sh │ └── management │ │ └── Dockerfile └── ubuntu │ ├── Dockerfile │ ├── docker-entrypoint.sh │ └── management │ └── Dockerfile ├── 3.8 ├── alpine │ ├── Dockerfile │ ├── docker-entrypoint.sh │ └── management │ │ └── Dockerfile └── ubuntu │ ├── Dockerfile │ ├── docker-entrypoint.sh │ └── management │ └── Dockerfile ├── Dockerfile-alpine.template ├── Dockerfile-management.template ├── Dockerfile-ubuntu.template ├── LICENSE ├── README.md ├── apply-templates.sh ├── docker-entrypoint.sh ├── generate-stackbrew-library.sh ├── update.sh ├── versions.json └── versions.sh /.gitattributes: -------------------------------------------------------------------------------- 1 | /*/**/Dockerfile linguist-generated 2 | /*/**/docker-entrypoint.sh linguist-generated 3 | /Dockerfile*.template linguist-language=Dockerfile 4 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: GitHub CI 2 | 3 | on: 4 | pull_request: 5 | push: 6 | schedule: 7 | - cron: 0 0 * * 0 8 | 9 | defaults: 10 | run: 11 | shell: 'bash -Eeuo pipefail -x {0}' 12 | 13 | jobs: 14 | 15 | generate-jobs: 16 | name: Generate Jobs 17 | runs-on: ubuntu-latest 18 | outputs: 19 | strategy: ${{ steps.generate-jobs.outputs.strategy }} 20 | steps: 21 | - uses: actions/checkout@v1 22 | - id: generate-jobs 23 | name: Generate Jobs 24 | run: | 25 | git clone --depth 1 https://github.com/docker-library/bashbrew.git -b master ~/bashbrew 26 | strategy="$(~/bashbrew/scripts/github-actions/generate.sh)" 27 | strategy="$(~/bashbrew/scripts/github-actions/munge-i386.sh -c <<<"$strategy")" 28 | jq . <<<"$strategy" # sanity check / debugging aid 29 | echo "::set-output name=strategy::$strategy" 30 | 31 | test: 32 | needs: generate-jobs 33 | strategy: ${{ fromJson(needs.generate-jobs.outputs.strategy) }} 34 | name: ${{ matrix.name }} 35 | runs-on: ${{ matrix.os }} 36 | steps: 37 | - uses: actions/checkout@v1 38 | - name: Prepare Environment 39 | run: ${{ matrix.runs.prepare }} 40 | - name: Pull Dependencies 41 | run: ${{ matrix.runs.pull }} 42 | - name: Build ${{ matrix.name }} 43 | run: ${{ matrix.runs.build }} 44 | - name: History ${{ matrix.name }} 45 | run: ${{ matrix.runs.history }} 46 | - name: Test ${{ matrix.name }} 47 | run: ${{ matrix.runs.test }} 48 | - name: '"docker images"' 49 | run: ${{ matrix.runs.images }} 50 | -------------------------------------------------------------------------------- /.github/workflows/verify-templating.yml: -------------------------------------------------------------------------------- 1 | name: Verify Templating 2 | 3 | on: 4 | pull_request: 5 | push: 6 | 7 | defaults: 8 | run: 9 | shell: 'bash -Eeuo pipefail -x {0}' 10 | 11 | jobs: 12 | apply-templates: 13 | name: Check For Uncomitted Changes 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Apply Templates 18 | run: ./apply-templates.sh 19 | - name: Check Git Status 20 | run: | 21 | status="$(git status --short)" 22 | [ -z "$status" ] 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .jq-template.awk 2 | -------------------------------------------------------------------------------- /3.8-rc/alpine/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | # Alpine Linux is not officially supported by the RabbitMQ team -- use at your own risk! 8 | FROM alpine:3.13 9 | 10 | RUN apk add --no-cache \ 11 | # grab su-exec for easy step-down from root 12 | 'su-exec>=0.2' \ 13 | # bash for docker-entrypoint.sh 14 | bash \ 15 | # "ps" for "rabbitmqctl wait" (https://github.com/docker-library/rabbitmq/issues/162) 16 | procps 17 | 18 | # Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally 19 | ARG PGP_KEYSERVER=ha.pool.sks-keyservers.net 20 | # If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, 21 | # run the build with a different PGP_KEYSERVER, e.g. docker build --tag rabbitmq:3.8 --build-arg PGP_KEYSERVER=pgpkeys.eu 3.8/ubuntu 22 | # For context, see https://github.com/docker-library/official-images/issues/4252 23 | 24 | ENV OPENSSL_VERSION 1.1.1j 25 | ENV OPENSSL_SOURCE_SHA256="aaf2fcb575cdf6491b98ab4829abf78a3dec8402b8b81efc8f23c00d443981bf" 26 | # https://www.openssl.org/community/omc.html 27 | ENV OPENSSL_PGP_KEY_IDS="0x8657ABB260F056B1E5190839D9C4D26D0E604491 0x5B2545DAB21995F4088CEFAA36CEE4DEB00CFE33 0xED230BEC4D4F2518B9D7DF41F0DB4D21C1D35231 0xC1F33DD8CE1D4CC613AF14DA9195C48241FBF7DD 0x7953AC1FBC3DC8B3B292393ED5E9E43F7DF9EE8C 0xE5E52560DD91C556DDBDA5D02064C53641C25E5D" 28 | 29 | ENV OTP_VERSION 23.2.5 30 | # TODO add PGP checking when the feature will be added to Erlang/OTP's build system 31 | # https://erlang.org/pipermail/erlang-questions/2019-January/097067.html 32 | ENV OTP_SOURCE_SHA256="0b1ca7d60f4f5a70b56cd0bef77cec2087a53a9a1812d5276a8cd4ce1acfa962" 33 | 34 | # Install dependencies required to build Erlang/OTP from source 35 | # https://erlang.org/doc/installation_guide/INSTALL.html 36 | # autoconf: Required to configure Erlang/OTP before compiling 37 | # dpkg-dev: Required to set up host & build type when compiling Erlang/OTP 38 | # gnupg: Required to verify OpenSSL artefacts 39 | # libncurses5-dev: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli 40 | RUN set -eux; \ 41 | \ 42 | apk add --no-cache --virtual .build-deps \ 43 | autoconf \ 44 | dpkg-dev dpkg \ 45 | gcc \ 46 | gnupg \ 47 | libc-dev \ 48 | linux-headers \ 49 | make \ 50 | ncurses-dev \ 51 | ; \ 52 | \ 53 | OPENSSL_SOURCE_URL="https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz"; \ 54 | OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ 55 | OPENSSL_CONFIG_DIR=/usr/local/etc/ssl; \ 56 | \ 57 | # /usr/local/src doesn't exist in Alpine by default 58 | mkdir /usr/local/src; \ 59 | \ 60 | # Required by the crypto & ssl Erlang/OTP applications 61 | wget --output-document "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_SOURCE_URL.asc"; \ 62 | wget --output-document "$OPENSSL_PATH.tar.gz" "$OPENSSL_SOURCE_URL"; \ 63 | export GNUPGHOME="$(mktemp -d)"; \ 64 | for key in $OPENSSL_PGP_KEY_IDS; do \ 65 | gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \ 66 | done; \ 67 | gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \ 68 | gpgconf --kill all; \ 69 | rm -rf "$GNUPGHOME"; \ 70 | echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum -c -; \ 71 | mkdir -p "$OPENSSL_PATH"; \ 72 | tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \ 73 | \ 74 | # Configure OpenSSL for compilation 75 | cd "$OPENSSL_PATH"; \ 76 | # OpenSSL's "config" script uses a lot of "uname"-based target detection... 77 | MACHINE="$(dpkg-architecture --query DEB_BUILD_GNU_CPU)" \ 78 | RELEASE="4.x.y-z" \ 79 | SYSTEM='Linux' \ 80 | BUILD='???' \ 81 | ./config \ 82 | --openssldir="$OPENSSL_CONFIG_DIR" \ 83 | # 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) 84 | -Wl,-rpath=/usr/local/lib \ 85 | ; \ 86 | # Compile, install OpenSSL, verify that the command-line works & development headers are present 87 | make -j "$(getconf _NPROCESSORS_ONLN)"; \ 88 | make install_sw install_ssldirs; \ 89 | cd ..; \ 90 | rm -rf "$OPENSSL_PATH"*; \ 91 | # use Alpine's CA certificates 92 | rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ 93 | ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR"; \ 94 | # smoke test 95 | openssl version; \ 96 | \ 97 | OTP_SOURCE_URL="https://github.com/erlang/otp/releases/download/OTP-$OTP_VERSION/otp_src_$OTP_VERSION.tar.gz"; \ 98 | OTP_PATH="/usr/local/src/otp-$OTP_VERSION"; \ 99 | \ 100 | # Download, verify & extract OTP_SOURCE 101 | mkdir -p "$OTP_PATH"; \ 102 | wget --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \ 103 | echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum -c -; \ 104 | tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \ 105 | \ 106 | # Configure Erlang/OTP for compilation, disable unused features & applications 107 | # https://erlang.org/doc/applications.html 108 | # ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation 109 | cd "$OTP_PATH"; \ 110 | export ERL_TOP="$OTP_PATH"; \ 111 | ./otp_build autoconf; \ 112 | export CFLAGS='-g -O2'; \ 113 | # 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) 114 | export CFLAGS="$CFLAGS -Wl,-rpath=/usr/local/lib"; \ 115 | hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ 116 | buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ 117 | dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ 118 | ./configure \ 119 | --host="$hostArch" \ 120 | --build="$buildArch" \ 121 | --disable-dynamic-ssl-lib \ 122 | --disable-hipe \ 123 | --disable-sctp \ 124 | --disable-silent-rules \ 125 | --enable-clock-gettime \ 126 | --enable-hybrid-heap \ 127 | --enable-kernel-poll \ 128 | --enable-shared-zlib \ 129 | --enable-smp-support \ 130 | --enable-threads \ 131 | --with-microstate-accounting=extra \ 132 | --without-common_test \ 133 | --without-debugger \ 134 | --without-dialyzer \ 135 | --without-diameter \ 136 | --without-edoc \ 137 | --without-erl_docgen \ 138 | --without-erl_interface \ 139 | --without-et \ 140 | --without-eunit \ 141 | --without-ftp \ 142 | --without-hipe \ 143 | --without-jinterface \ 144 | --without-megaco \ 145 | --without-observer \ 146 | --without-odbc \ 147 | --without-reltool \ 148 | --without-ssh \ 149 | --without-tftp \ 150 | --without-wx \ 151 | ; \ 152 | # Compile & install Erlang/OTP 153 | make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ 154 | make install; \ 155 | cd ..; \ 156 | rm -rf \ 157 | "$OTP_PATH"* \ 158 | /usr/local/lib/erlang/lib/*/examples \ 159 | /usr/local/lib/erlang/lib/*/src \ 160 | ; \ 161 | \ 162 | runDeps="$( \ 163 | scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ 164 | | tr ',' '\n' \ 165 | | sort -u \ 166 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 167 | )"; \ 168 | apk add --no-cache --virtual .otp-run-deps $runDeps; \ 169 | apk del --no-network .build-deps; \ 170 | \ 171 | # Check that OpenSSL still works after purging build dependencies 172 | openssl version; \ 173 | # Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly 174 | erl -noshell -eval 'io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' 175 | 176 | ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq 177 | # Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM 178 | RUN set -eux; \ 179 | addgroup -g 101 -S rabbitmq; \ 180 | adduser -u 100 -S -h "$RABBITMQ_DATA_DIR" -G rabbitmq rabbitmq; \ 181 | mkdir -p "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 182 | chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 183 | chmod 777 "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 184 | ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie 185 | 186 | # Use the latest stable RabbitMQ release (https://www.rabbitmq.com/download.html) 187 | ENV RABBITMQ_VERSION 3.8.12-rc.3 188 | # https://www.rabbitmq.com/signatures.html#importing-gpg 189 | ENV RABBITMQ_PGP_KEY_ID="0x0A9AF2115F4687BD29803A206B73A36E6026DFCA" 190 | ENV RABBITMQ_HOME=/opt/rabbitmq 191 | 192 | # Add RabbitMQ to PATH, send all logs to TTY 193 | ENV PATH=$RABBITMQ_HOME/sbin:$PATH \ 194 | RABBITMQ_LOGS=- 195 | 196 | # Install RabbitMQ 197 | RUN set -eux; \ 198 | \ 199 | apk add --no-cache --virtual .build-deps \ 200 | gnupg \ 201 | xz \ 202 | ; \ 203 | \ 204 | RABBITMQ_SOURCE_URL="https://github.com/rabbitmq/rabbitmq-server/releases/download/v$RABBITMQ_VERSION/rabbitmq-server-generic-unix-latest-toolchain-$RABBITMQ_VERSION.tar.xz"; \ 205 | RABBITMQ_PATH="/usr/local/src/rabbitmq-$RABBITMQ_VERSION"; \ 206 | \ 207 | wget --output-document "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_SOURCE_URL.asc"; \ 208 | wget --output-document "$RABBITMQ_PATH.tar.xz" "$RABBITMQ_SOURCE_URL"; \ 209 | \ 210 | export GNUPGHOME="$(mktemp -d)"; \ 211 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$RABBITMQ_PGP_KEY_ID"; \ 212 | gpg --batch --verify "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_PATH.tar.xz"; \ 213 | gpgconf --kill all; \ 214 | rm -rf "$GNUPGHOME"; \ 215 | \ 216 | mkdir -p "$RABBITMQ_HOME"; \ 217 | tar --extract --file "$RABBITMQ_PATH.tar.xz" --directory "$RABBITMQ_HOME" --strip-components 1; \ 218 | rm -rf "$RABBITMQ_PATH"*; \ 219 | # Do not default SYS_PREFIX to RABBITMQ_HOME, leave it empty 220 | grep -qE '^SYS_PREFIX=\$\{RABBITMQ_HOME\}$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 221 | sed -i 's/^SYS_PREFIX=.*$/SYS_PREFIX=/' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 222 | grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 223 | chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ 224 | \ 225 | apk del .build-deps; \ 226 | \ 227 | # verify assumption of no stale cookies 228 | [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ 229 | # Ensure RabbitMQ was installed correctly by running a few commands that do not depend on a running server, as the rabbitmq user 230 | # If they all succeed, it's safe to assume that things have been set up correctly 231 | su-exec rabbitmq rabbitmqctl help; \ 232 | su-exec rabbitmq rabbitmqctl list_ciphers; \ 233 | su-exec rabbitmq rabbitmq-plugins list; \ 234 | # no stale cookies 235 | rm "$RABBITMQ_DATA_DIR/.erlang.cookie" 236 | 237 | # Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) 238 | RUN set -eux; \ 239 | rabbitmq-plugins enable --offline rabbitmq_prometheus; \ 240 | echo 'management_agent.disable_metrics_collector = true' > /etc/rabbitmq/conf.d/management_agent.disable_metrics_collector.conf 241 | 242 | # Added for backwards compatibility - users can simply COPY custom plugins to /plugins 243 | RUN ln -sf /opt/rabbitmq/plugins /plugins 244 | 245 | # set home so that any `--user` knows where to put the erlang cookie 246 | ENV HOME $RABBITMQ_DATA_DIR 247 | # Hint that the data (a.k.a. home dir) dir should be separate volume 248 | VOLUME $RABBITMQ_DATA_DIR 249 | 250 | # 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) 251 | # 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 252 | # https://docs.docker.com/samples/library/ubuntu/#locales 253 | ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 254 | 255 | COPY docker-entrypoint.sh /usr/local/bin/ 256 | ENTRYPOINT ["docker-entrypoint.sh"] 257 | 258 | EXPOSE 4369 5671 5672 15691 15692 25672 259 | CMD ["rabbitmq-server"] 260 | -------------------------------------------------------------------------------- /3.8-rc/alpine/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eu 3 | 4 | # usage: file_env VAR [DEFAULT] 5 | # ie: file_env 'XYZ_DB_PASSWORD' 'example' 6 | # (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of 7 | # "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) 8 | file_env() { 9 | local var="$1" 10 | local fileVar="${var}_FILE" 11 | local def="${2:-}" 12 | if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then 13 | echo >&2 "error: both $var and $fileVar are set (but are exclusive)" 14 | exit 1 15 | fi 16 | local val="$def" 17 | if [ "${!var:-}" ]; then 18 | val="${!var}" 19 | elif [ "${!fileVar:-}" ]; then 20 | val="$(< "${!fileVar}")" 21 | fi 22 | export "$var"="$val" 23 | unset "$fileVar" 24 | } 25 | 26 | # backwards compatibility for old environment variables 27 | : "${RABBITMQ_SSL_CERTFILE:=${RABBITMQ_SSL_CERT_FILE:-}}" 28 | : "${RABBITMQ_SSL_KEYFILE:=${RABBITMQ_SSL_KEY_FILE:-}}" 29 | : "${RABBITMQ_SSL_CACERTFILE:=${RABBITMQ_SSL_CA_FILE:-}}" 30 | 31 | # "management" SSL config should default to using the same certs 32 | : "${RABBITMQ_MANAGEMENT_SSL_CACERTFILE:=$RABBITMQ_SSL_CACERTFILE}" 33 | : "${RABBITMQ_MANAGEMENT_SSL_CERTFILE:=$RABBITMQ_SSL_CERTFILE}" 34 | : "${RABBITMQ_MANAGEMENT_SSL_KEYFILE:=$RABBITMQ_SSL_KEYFILE}" 35 | 36 | # Allowed env vars that will be read from mounted files (i.e. Docker Secrets): 37 | fileEnvKeys=( 38 | default_user 39 | default_pass 40 | ) 41 | 42 | # https://www.rabbitmq.com/configure.html 43 | sslConfigKeys=( 44 | cacertfile 45 | certfile 46 | depth 47 | fail_if_no_peer_cert 48 | keyfile 49 | verify 50 | ) 51 | managementConfigKeys=( 52 | "${sslConfigKeys[@]/#/ssl_}" 53 | ) 54 | rabbitConfigKeys=( 55 | default_pass 56 | default_user 57 | default_vhost 58 | vm_memory_high_watermark 59 | ) 60 | fileConfigKeys=( 61 | management_ssl_cacertfile 62 | management_ssl_certfile 63 | management_ssl_keyfile 64 | ssl_cacertfile 65 | ssl_certfile 66 | ssl_keyfile 67 | ) 68 | allConfigKeys=( 69 | "${managementConfigKeys[@]/#/management_}" 70 | "${rabbitConfigKeys[@]}" 71 | "${sslConfigKeys[@]/#/ssl_}" 72 | ) 73 | 74 | declare -A configDefaults=( 75 | [management_ssl_fail_if_no_peer_cert]='false' 76 | [management_ssl_verify]='verify_none' 77 | 78 | [ssl_fail_if_no_peer_cert]='true' 79 | [ssl_verify]='verify_peer' 80 | ) 81 | 82 | # allow the container to be started with `--user` 83 | if [[ "$1" == rabbitmq* ]] && [ "$(id -u)" = '0' ]; then 84 | # this needs to happen late enough that we have the SSL config 85 | # https://github.com/docker-library/rabbitmq/issues/283 86 | for conf in "${allConfigKeys[@]}"; do 87 | var="RABBITMQ_${conf^^}" 88 | val="${!var:-}" 89 | [ -n "$val" ] || continue 90 | case "$conf" in 91 | *_ssl_*file | ssl_*file ) 92 | if [ -f "$val" ] && ! su-exec rabbitmq test -r "$val"; then 93 | newFile="/tmp/rabbitmq-ssl/$conf.pem" 94 | echo >&2 95 | echo >&2 "WARNING: '$val' ($var) is not readable by rabbitmq ($(id rabbitmq)); copying to '$newFile'" 96 | echo >&2 97 | cat "$val" > "$newFile" 98 | chown rabbitmq "$newFile" 99 | chmod 0400 "$newFile" 100 | eval 'export '$var'="$newFile"' 101 | fi 102 | ;; 103 | esac 104 | done 105 | 106 | if [ "$1" = 'rabbitmq-server' ]; then 107 | find /var/lib/rabbitmq \! -user rabbitmq -exec chown rabbitmq '{}' + 108 | fi 109 | 110 | exec su-exec rabbitmq "$BASH_SOURCE" "$@" 111 | fi 112 | 113 | haveConfig= 114 | haveSslConfig= 115 | haveManagementSslConfig= 116 | for fileEnvKey in "${fileEnvKeys[@]}"; do file_env "RABBITMQ_${fileEnvKey^^}"; done 117 | for conf in "${allConfigKeys[@]}"; do 118 | var="RABBITMQ_${conf^^}" 119 | val="${!var:-}" 120 | if [ "$val" ]; then 121 | if [ "${configDefaults[$conf]:-}" ] && [ "${configDefaults[$conf]}" = "$val" ]; then 122 | # if the value set is the same as the default, treat it as if it isn't set 123 | continue 124 | fi 125 | haveConfig=1 126 | case "$conf" in 127 | ssl_*) haveSslConfig=1 ;; 128 | management_ssl_*) haveManagementSslConfig=1 ;; 129 | esac 130 | fi 131 | done 132 | if [ "$haveSslConfig" ]; then 133 | missing=() 134 | for sslConf in cacertfile certfile keyfile; do 135 | var="RABBITMQ_SSL_${sslConf^^}" 136 | val="${!var}" 137 | if [ -z "$val" ]; then 138 | missing+=( "$var" ) 139 | fi 140 | done 141 | if [ "${#missing[@]}" -gt 0 ]; then 142 | { 143 | echo 144 | echo 'error: SSL requested, but missing required configuration' 145 | for miss in "${missing[@]}"; do 146 | echo " - $miss" 147 | done 148 | echo 149 | } >&2 150 | exit 1 151 | fi 152 | fi 153 | missingFiles=() 154 | for conf in "${fileConfigKeys[@]}"; do 155 | var="RABBITMQ_${conf^^}" 156 | val="${!var}" 157 | if [ "$val" ] && [ ! -f "$val" ]; then 158 | missingFiles+=( "$val ($var)" ) 159 | fi 160 | done 161 | if [ "${#missingFiles[@]}" -gt 0 ]; then 162 | { 163 | echo 164 | echo 'error: files specified, but missing' 165 | for miss in "${missingFiles[@]}"; do 166 | echo " - $miss" 167 | done 168 | echo 169 | } >&2 170 | exit 1 171 | fi 172 | 173 | # set defaults for missing values (but only after we're done with all our checking so we don't throw any of that off) 174 | for conf in "${!configDefaults[@]}"; do 175 | default="${configDefaults[$conf]}" 176 | var="RABBITMQ_${conf^^}" 177 | [ -z "${!var:-}" ] || continue 178 | eval "export $var=\"\$default\"" 179 | done 180 | 181 | # if long and short hostnames are not the same, use long hostnames 182 | if [ "$(hostname)" != "$(hostname -s)" ]; then 183 | : "${RABBITMQ_USE_LONGNAME:=true}" 184 | fi 185 | 186 | if [ "${RABBITMQ_ERLANG_COOKIE:-}" ]; then 187 | cookieFile='/var/lib/rabbitmq/.erlang.cookie' 188 | if [ -e "$cookieFile" ]; then 189 | if [ "$(cat "$cookieFile" 2>/dev/null)" != "$RABBITMQ_ERLANG_COOKIE" ]; then 190 | echo >&2 191 | echo >&2 "warning: $cookieFile contents do not match RABBITMQ_ERLANG_COOKIE" 192 | echo >&2 193 | fi 194 | else 195 | echo "$RABBITMQ_ERLANG_COOKIE" > "$cookieFile" 196 | fi 197 | chmod 600 "$cookieFile" 198 | fi 199 | 200 | configBase="${RABBITMQ_CONFIG_FILE:-/etc/rabbitmq/rabbitmq}" 201 | oldConfigFile="$configBase.config" 202 | newConfigFile="$configBase.conf" 203 | 204 | shouldWriteConfig="$haveConfig" 205 | if [ -n "$shouldWriteConfig" ] && ! touch "$newConfigFile"; then 206 | # config file exists but it isn't writeable (likely read-only mount, such as Kubernetes configMap) 207 | export RABBITMQ_CONFIG_FILE='/tmp/rabbitmq.conf' 208 | cp "$newConfigFile" "$RABBITMQ_CONFIG_FILE" 209 | echo >&2 210 | echo >&2 "WARNING: '$newConfigFile' is not writable, but environment variables have been provided which request that we write to it" 211 | echo >&2 " We have copied it to '$RABBITMQ_CONFIG_FILE' so it can be amended to work around the problem, but it is recommended that the read-only source file should be modified and the environment variables removed instead." 212 | echo >&2 213 | newConfigFile="$RABBITMQ_CONFIG_FILE" 214 | fi 215 | if [ -n "$shouldWriteConfig" ] && [ -f "$oldConfigFile" ]; then 216 | { 217 | echo "error: Docker configuration environment variables specified, but old-style (Erlang syntax) configuration file '$oldConfigFile' exists" 218 | echo " Suggested fixes: (choose one)" 219 | echo " - remove '$oldConfigFile'" 220 | echo " - remove any Docker-specific 'RABBITMQ_...' environment variables" 221 | echo " - convert '$oldConfigFile' to the newer sysctl format ('$newConfigFile'); see https://www.rabbitmq.com/configure.html#config-file" 222 | } >&2 223 | exit 1 224 | fi 225 | if [ -z "$shouldWriteConfig" ] && [ ! -f "$oldConfigFile" ] && [ ! -f "$newConfigFile" ]; then 226 | # no config files, we should write one 227 | shouldWriteConfig=1 228 | fi 229 | 230 | # http://stackoverflow.com/a/2705678/433558 231 | sed_escape_lhs() { 232 | echo "$@" | sed -e 's/[]\/$*.^|[]/\\&/g' 233 | } 234 | sed_escape_rhs() { 235 | echo "$@" | sed -e 's/[\/&]/\\&/g' 236 | } 237 | rabbit_set_config() { 238 | local key="$1"; shift 239 | local val="$1"; shift 240 | 241 | [ -e "$newConfigFile" ] || touch "$newConfigFile" 242 | 243 | local sedKey="$(sed_escape_lhs "$key")" 244 | local sedVal="$(sed_escape_rhs "$val")" 245 | sed -ri \ 246 | "s/^[[:space:]]*(${sedKey}[[:space:]]*=[[:space:]]*)\S.*\$/\1${sedVal}/" \ 247 | "$newConfigFile" 248 | if ! grep -qE "^${sedKey}[[:space:]]*=" "$newConfigFile"; then 249 | sed -i -e '$a\' "$newConfigFile" # https://github.com/docker-library/rabbitmq/issues/456#issuecomment-752251872 (https://unix.stackexchange.com/a/31955/153467) 250 | echo "$key = $val" >> "$newConfigFile" 251 | fi 252 | } 253 | rabbit_comment_config() { 254 | local key="$1"; shift 255 | 256 | [ -e "$newConfigFile" ] || touch "$newConfigFile" 257 | 258 | local sedKey="$(sed_escape_lhs "$key")" 259 | sed -ri \ 260 | "s/^[[:space:]]*#?[[:space:]]*(${sedKey}[[:space:]]*=[[:space:]]*\S.*)\$/# \1/" \ 261 | "$newConfigFile" 262 | } 263 | rabbit_env_config() { 264 | local prefix="$1"; shift 265 | 266 | local conf 267 | for conf; do 268 | local var="rabbitmq${prefix:+_$prefix}_$conf" 269 | var="${var^^}" 270 | 271 | local key="$conf" 272 | case "$prefix" in 273 | ssl) key="ssl_options.$key" ;; 274 | management_ssl) key="management.ssl.$key" ;; 275 | esac 276 | 277 | local val="${!var:-}" 278 | local rawVal="$val" 279 | case "$conf" in 280 | fail_if_no_peer_cert) 281 | case "${val,,}" in 282 | false|no|0|'') rawVal='false' ;; 283 | true|yes|1|*) rawVal='true' ;; 284 | esac 285 | ;; 286 | 287 | vm_memory_high_watermark) continue ;; # handled separately 288 | esac 289 | 290 | if [ -n "$rawVal" ]; then 291 | rabbit_set_config "$key" "$rawVal" 292 | else 293 | rabbit_comment_config "$key" 294 | fi 295 | done 296 | } 297 | 298 | if [ "$1" = 'rabbitmq-server' ] && [ "$shouldWriteConfig" ]; then 299 | rabbit_set_config 'loopback_users.guest' 'false' 300 | 301 | # determine whether to set "vm_memory_high_watermark" (based on cgroups) 302 | memTotalKb= 303 | if [ -r /proc/meminfo ]; then 304 | memTotalKb="$(awk -F ':? +' '$1 == "MemTotal" { print $2; exit }' /proc/meminfo)" 305 | fi 306 | memLimitB= 307 | if [ -r /sys/fs/cgroup/memory/memory.limit_in_bytes ]; then 308 | # "18446744073709551615" is a valid value for "memory.limit_in_bytes", which is too big for Bash math to handle 309 | # "$(( 18446744073709551615 / 1024 ))" = 0; "$(( 18446744073709551615 * 40 / 100 ))" = 0 310 | memLimitB="$(awk -v totKb="$memTotalKb" '{ 311 | limB = $0; 312 | limKb = limB / 1024; 313 | if (!totKb || limKb < totKb) { 314 | printf "%.0f\n", limB; 315 | } 316 | }' /sys/fs/cgroup/memory/memory.limit_in_bytes)" 317 | fi 318 | if [ -n "$memLimitB" ]; then 319 | # if we have a cgroup memory limit, let's inform RabbitMQ of what it is (so it can calculate vm_memory_high_watermark properly) 320 | # https://github.com/rabbitmq/rabbitmq-server/pull/1234 321 | rabbit_set_config 'total_memory_available_override_value' "$memLimitB" 322 | fi 323 | # https://www.rabbitmq.com/memory.html#memsup-usage 324 | if [ "${RABBITMQ_VM_MEMORY_HIGH_WATERMARK:-}" ]; then 325 | # https://github.com/docker-library/rabbitmq/pull/105#issuecomment-242165822 326 | vmMemoryHighWatermark="$( 327 | echo "$RABBITMQ_VM_MEMORY_HIGH_WATERMARK" | awk ' 328 | /^[0-9]*[.][0-9]+$|^[0-9]+([.][0-9]+)?%$/ { 329 | perc = $0; 330 | if (perc ~ /%$/) { 331 | gsub(/%$/, "", perc); 332 | perc = perc / 100; 333 | } 334 | if (perc > 1.0 || perc < 0.0) { 335 | printf "error: invalid percentage for vm_memory_high_watermark: %s (must be >= 0%%, <= 100%%)\n", $0 > "/dev/stderr"; 336 | exit 1; 337 | } 338 | printf "vm_memory_high_watermark.relative %0.03f\n", perc; 339 | next; 340 | } 341 | /^[0-9]+$/ { 342 | printf "vm_memory_high_watermark.absolute %s\n", $0; 343 | next; 344 | } 345 | /^[0-9]+([.][0-9]+)?[a-zA-Z]+$/ { 346 | printf "vm_memory_high_watermark.absolute %s\n", $0; 347 | next; 348 | } 349 | { 350 | printf "error: unexpected input for vm_memory_high_watermark: %s\n", $0; 351 | exit 1; 352 | } 353 | ' 354 | )" 355 | if [ "$vmMemoryHighWatermark" ]; then 356 | vmMemoryHighWatermarkKey="${vmMemoryHighWatermark%% *}" 357 | vmMemoryHighWatermarkVal="${vmMemoryHighWatermark#$vmMemoryHighWatermarkKey }" 358 | rabbit_set_config "$vmMemoryHighWatermarkKey" "$vmMemoryHighWatermarkVal" 359 | case "$vmMemoryHighWatermarkKey" in 360 | # make sure we only set one or the other 361 | 'vm_memory_high_watermark.absolute') rabbit_comment_config 'vm_memory_high_watermark.relative' ;; 362 | 'vm_memory_high_watermark.relative') rabbit_comment_config 'vm_memory_high_watermark.absolute' ;; 363 | esac 364 | fi 365 | fi 366 | 367 | if [ "$haveSslConfig" ]; then 368 | rabbit_set_config 'listeners.ssl.default' 5671 369 | rabbit_env_config 'ssl' "${sslConfigKeys[@]}" 370 | else 371 | rabbit_set_config 'listeners.tcp.default' 5672 372 | fi 373 | 374 | rabbit_env_config '' "${rabbitConfigKeys[@]}" 375 | 376 | # if management plugin is installed, generate config for it 377 | # https://www.rabbitmq.com/management.html#configuration 378 | if [ "$(rabbitmq-plugins list -q -m -e rabbitmq_management)" ]; then 379 | if [ "$haveManagementSslConfig" ]; then 380 | rabbit_set_config 'management.ssl.port' 15671 381 | rabbit_env_config 'management_ssl' "${sslConfigKeys[@]}" 382 | else 383 | rabbit_set_config 'management.tcp.port' 15672 384 | fi 385 | 386 | # if definitions file exists, then load it 387 | # https://www.rabbitmq.com/management.html#load-definitions 388 | managementDefinitionsFile='/etc/rabbitmq/definitions.json' 389 | if [ -f "$managementDefinitionsFile" ]; then 390 | # We use `load_definitions` (the built-in setting as of 3.8.2+) instead 391 | # of `management.load_definitions`. 392 | # See https://github.com/docker-library/rabbitmq/issues/429 for details. 393 | rabbit_set_config 'load_definitions' "$managementDefinitionsFile" 394 | fi 395 | fi 396 | fi 397 | 398 | combinedSsl='/tmp/rabbitmq-ssl/combined.pem' 399 | if [ "$haveSslConfig" ] && [[ "$1" == rabbitmq* ]] && [ ! -f "$combinedSsl" ]; then 400 | # Create combined cert 401 | { 402 | cat "$RABBITMQ_SSL_CERTFILE" 403 | echo # https://github.com/docker-library/rabbitmq/issues/357#issuecomment-517755647 404 | cat "$RABBITMQ_SSL_KEYFILE" 405 | } > "$combinedSsl" 406 | chmod 0400 "$combinedSsl" 407 | fi 408 | if [ "$haveSslConfig" ] && [ -f "$combinedSsl" ]; then 409 | # More ENV vars for make clustering happiness 410 | # we don't handle clustering in this script, but these args should ensure 411 | # clustered SSL-enabled members will talk nicely 412 | export ERL_SSL_PATH="$(erl -eval 'io:format("~p", [code:lib_dir(ssl, ebin)]),halt().' -noshell)" 413 | sslErlArgs="-pa $ERL_SSL_PATH -proto_dist inet_tls -ssl_dist_opt server_certfile $combinedSsl -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true" 414 | export RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="${RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS:-} $sslErlArgs" 415 | export RABBITMQ_CTL_ERL_ARGS="${RABBITMQ_CTL_ERL_ARGS:-} $sslErlArgs" 416 | fi 417 | 418 | exec "$@" 419 | -------------------------------------------------------------------------------- /3.8-rc/alpine/management/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM rabbitmq:3.8-rc-alpine 8 | 9 | RUN rabbitmq-plugins enable --offline rabbitmq_management 10 | 11 | # make sure the metrics collector is re-enabled (disabled in the base image for Prometheus-style metrics by default) 12 | RUN rm -f /etc/rabbitmq/conf.d/management_agent.disable_metrics_collector.conf 13 | 14 | # extract "rabbitmqadmin" from inside the "rabbitmq_management-X.Y.Z.ez" plugin zipfile 15 | # see https://github.com/docker-library/rabbitmq/issues/207 16 | RUN set -eux; \ 17 | erl -noinput -eval ' \ 18 | { ok, AdminBin } = zip:foldl(fun(FileInArchive, GetInfo, GetBin, Acc) -> \ 19 | case Acc of \ 20 | "" -> \ 21 | case lists:suffix("/rabbitmqadmin", FileInArchive) of \ 22 | true -> GetBin(); \ 23 | false -> Acc \ 24 | end; \ 25 | _ -> Acc \ 26 | end \ 27 | end, "", init:get_plain_arguments()), \ 28 | io:format("~s", [ AdminBin ]), \ 29 | init:stop(). \ 30 | ' -- /plugins/rabbitmq_management-*.ez > /usr/local/bin/rabbitmqadmin; \ 31 | [ -s /usr/local/bin/rabbitmqadmin ]; \ 32 | chmod +x /usr/local/bin/rabbitmqadmin; \ 33 | apk add --no-cache python3; \ 34 | rabbitmqadmin --version 35 | 36 | EXPOSE 15671 15672 37 | -------------------------------------------------------------------------------- /3.8-rc/ubuntu/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | # The official Canonical Ubuntu Bionic image is ideal from a security perspective, 8 | # especially for the enterprises that we, the RabbitMQ team, have to deal with 9 | FROM ubuntu:18.04 10 | 11 | RUN set -eux; \ 12 | apt-get update; \ 13 | apt-get install -y --no-install-recommends \ 14 | # grab gosu for easy step-down from root 15 | gosu \ 16 | ; \ 17 | rm -rf /var/lib/apt/lists/*; \ 18 | # verify that the "gosu" binary works 19 | gosu nobody true 20 | 21 | # Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally 22 | ARG PGP_KEYSERVER=ha.pool.sks-keyservers.net 23 | # If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, 24 | # run the build with a different PGP_KEYSERVER, e.g. docker build --tag rabbitmq:3.8 --build-arg PGP_KEYSERVER=pgpkeys.eu 3.8/ubuntu 25 | # For context, see https://github.com/docker-library/official-images/issues/4252 26 | 27 | ENV OPENSSL_VERSION 1.1.1j 28 | ENV OPENSSL_SOURCE_SHA256="aaf2fcb575cdf6491b98ab4829abf78a3dec8402b8b81efc8f23c00d443981bf" 29 | # https://www.openssl.org/community/omc.html 30 | ENV OPENSSL_PGP_KEY_IDS="0x8657ABB260F056B1E5190839D9C4D26D0E604491 0x5B2545DAB21995F4088CEFAA36CEE4DEB00CFE33 0xED230BEC4D4F2518B9D7DF41F0DB4D21C1D35231 0xC1F33DD8CE1D4CC613AF14DA9195C48241FBF7DD 0x7953AC1FBC3DC8B3B292393ED5E9E43F7DF9EE8C 0xE5E52560DD91C556DDBDA5D02064C53641C25E5D" 31 | 32 | ENV OTP_VERSION 23.2.5 33 | # TODO add PGP checking when the feature will be added to Erlang/OTP's build system 34 | # https://erlang.org/pipermail/erlang-questions/2019-January/097067.html 35 | ENV OTP_SOURCE_SHA256="0b1ca7d60f4f5a70b56cd0bef77cec2087a53a9a1812d5276a8cd4ce1acfa962" 36 | 37 | # Install dependencies required to build Erlang/OTP from source 38 | # https://erlang.org/doc/installation_guide/INSTALL.html 39 | # autoconf: Required to configure Erlang/OTP before compiling 40 | # dpkg-dev: Required to set up host & build type when compiling Erlang/OTP 41 | # gnupg: Required to verify OpenSSL artefacts 42 | # libncurses5-dev: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli 43 | RUN set -eux; \ 44 | \ 45 | savedAptMark="$(apt-mark showmanual)"; \ 46 | apt-get update; \ 47 | apt-get install --yes --no-install-recommends \ 48 | autoconf \ 49 | ca-certificates \ 50 | dpkg-dev \ 51 | gcc \ 52 | gnupg \ 53 | libncurses5-dev \ 54 | make \ 55 | wget \ 56 | ; \ 57 | rm -rf /var/lib/apt/lists/*; \ 58 | \ 59 | OPENSSL_SOURCE_URL="https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz"; \ 60 | OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ 61 | OPENSSL_CONFIG_DIR=/usr/local/etc/ssl; \ 62 | \ 63 | # Required by the crypto & ssl Erlang/OTP applications 64 | wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_SOURCE_URL.asc"; \ 65 | wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz" "$OPENSSL_SOURCE_URL"; \ 66 | export GNUPGHOME="$(mktemp -d)"; \ 67 | for key in $OPENSSL_PGP_KEY_IDS; do \ 68 | gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \ 69 | done; \ 70 | gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \ 71 | gpgconf --kill all; \ 72 | rm -rf "$GNUPGHOME"; \ 73 | echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum --check --strict -; \ 74 | mkdir -p "$OPENSSL_PATH"; \ 75 | tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \ 76 | \ 77 | # Configure OpenSSL for compilation 78 | cd "$OPENSSL_PATH"; \ 79 | # without specifying "--libdir", Erlang will fail during "crypto:supports()" looking for a "pthread_atfork" function that doesn't exist (but only on arm32v7/armhf??) 80 | debMultiarch="$(dpkg-architecture --query DEB_HOST_MULTIARCH)"; \ 81 | # OpenSSL's "config" script uses a lot of "uname"-based target detection... 82 | MACHINE="$(dpkg-architecture --query DEB_BUILD_GNU_CPU)" \ 83 | RELEASE="4.x.y-z" \ 84 | SYSTEM='Linux' \ 85 | BUILD='???' \ 86 | ./config \ 87 | --openssldir="$OPENSSL_CONFIG_DIR" \ 88 | --libdir="lib/$debMultiarch" \ 89 | # 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) 90 | -Wl,-rpath=/usr/local/lib \ 91 | ; \ 92 | # Compile, install OpenSSL, verify that the command-line works & development headers are present 93 | make -j "$(getconf _NPROCESSORS_ONLN)"; \ 94 | make install_sw install_ssldirs; \ 95 | cd ..; \ 96 | rm -rf "$OPENSSL_PATH"*; \ 97 | ldconfig; \ 98 | # use Debian's CA certificates 99 | rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ 100 | ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR"; \ 101 | # smoke test 102 | openssl version; \ 103 | \ 104 | OTP_SOURCE_URL="https://github.com/erlang/otp/releases/download/OTP-$OTP_VERSION/otp_src_$OTP_VERSION.tar.gz"; \ 105 | OTP_PATH="/usr/local/src/otp-$OTP_VERSION"; \ 106 | \ 107 | # Download, verify & extract OTP_SOURCE 108 | mkdir -p "$OTP_PATH"; \ 109 | wget --progress dot:giga --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \ 110 | echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum --check --strict -; \ 111 | tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \ 112 | \ 113 | # Configure Erlang/OTP for compilation, disable unused features & applications 114 | # https://erlang.org/doc/applications.html 115 | # ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation 116 | cd "$OTP_PATH"; \ 117 | export ERL_TOP="$OTP_PATH"; \ 118 | ./otp_build autoconf; \ 119 | CFLAGS="$(dpkg-buildflags --get CFLAGS)"; export CFLAGS; \ 120 | # 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) 121 | export CFLAGS="$CFLAGS -Wl,-rpath=/usr/local/lib"; \ 122 | hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ 123 | buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ 124 | dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ 125 | ./configure \ 126 | --host="$hostArch" \ 127 | --build="$buildArch" \ 128 | --disable-dynamic-ssl-lib \ 129 | --disable-hipe \ 130 | --disable-sctp \ 131 | --disable-silent-rules \ 132 | --enable-clock-gettime \ 133 | --enable-hybrid-heap \ 134 | --enable-kernel-poll \ 135 | --enable-shared-zlib \ 136 | --enable-smp-support \ 137 | --enable-threads \ 138 | --with-microstate-accounting=extra \ 139 | --without-common_test \ 140 | --without-debugger \ 141 | --without-dialyzer \ 142 | --without-diameter \ 143 | --without-edoc \ 144 | --without-erl_docgen \ 145 | --without-erl_interface \ 146 | --without-et \ 147 | --without-eunit \ 148 | --without-ftp \ 149 | --without-hipe \ 150 | --without-jinterface \ 151 | --without-megaco \ 152 | --without-observer \ 153 | --without-odbc \ 154 | --without-reltool \ 155 | --without-ssh \ 156 | --without-tftp \ 157 | --without-wx \ 158 | ; \ 159 | # Compile & install Erlang/OTP 160 | make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ 161 | make install; \ 162 | cd ..; \ 163 | rm -rf \ 164 | "$OTP_PATH"* \ 165 | /usr/local/lib/erlang/lib/*/examples \ 166 | /usr/local/lib/erlang/lib/*/src \ 167 | ; \ 168 | \ 169 | # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies 170 | apt-mark auto '.*' > /dev/null; \ 171 | [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \ 172 | find /usr/local -type f -executable -exec ldd '{}' ';' \ 173 | | awk '/=>/ { print $(NF-1) }' \ 174 | | sort -u \ 175 | | xargs -r dpkg-query --search \ 176 | | cut -d: -f1 \ 177 | | sort -u \ 178 | | xargs -r apt-mark manual \ 179 | ; \ 180 | apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ 181 | \ 182 | # Check that OpenSSL still works after purging build dependencies 183 | openssl version; \ 184 | # Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly 185 | erl -noshell -eval 'io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' 186 | 187 | ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq 188 | # Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM 189 | RUN set -eux; \ 190 | groupadd --gid 999 --system rabbitmq; \ 191 | useradd --uid 999 --system --home-dir "$RABBITMQ_DATA_DIR" --gid rabbitmq rabbitmq; \ 192 | mkdir -p "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 193 | chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 194 | chmod 777 "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 195 | ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie 196 | 197 | # Use the latest stable RabbitMQ release (https://www.rabbitmq.com/download.html) 198 | ENV RABBITMQ_VERSION 3.8.12-rc.3 199 | # https://www.rabbitmq.com/signatures.html#importing-gpg 200 | ENV RABBITMQ_PGP_KEY_ID="0x0A9AF2115F4687BD29803A206B73A36E6026DFCA" 201 | ENV RABBITMQ_HOME=/opt/rabbitmq 202 | 203 | # Add RabbitMQ to PATH, send all logs to TTY 204 | ENV PATH=$RABBITMQ_HOME/sbin:$PATH \ 205 | RABBITMQ_LOGS=- 206 | 207 | # Install RabbitMQ 208 | RUN set -eux; \ 209 | \ 210 | savedAptMark="$(apt-mark showmanual)"; \ 211 | apt-get update; \ 212 | apt-get install --yes --no-install-recommends \ 213 | ca-certificates \ 214 | gnupg \ 215 | wget \ 216 | xz-utils \ 217 | ; \ 218 | rm -rf /var/lib/apt/lists/*; \ 219 | \ 220 | RABBITMQ_SOURCE_URL="https://github.com/rabbitmq/rabbitmq-server/releases/download/v$RABBITMQ_VERSION/rabbitmq-server-generic-unix-latest-toolchain-$RABBITMQ_VERSION.tar.xz"; \ 221 | RABBITMQ_PATH="/usr/local/src/rabbitmq-$RABBITMQ_VERSION"; \ 222 | \ 223 | wget --progress dot:giga --output-document "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_SOURCE_URL.asc"; \ 224 | wget --progress dot:giga --output-document "$RABBITMQ_PATH.tar.xz" "$RABBITMQ_SOURCE_URL"; \ 225 | \ 226 | export GNUPGHOME="$(mktemp -d)"; \ 227 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$RABBITMQ_PGP_KEY_ID"; \ 228 | gpg --batch --verify "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_PATH.tar.xz"; \ 229 | gpgconf --kill all; \ 230 | rm -rf "$GNUPGHOME"; \ 231 | \ 232 | mkdir -p "$RABBITMQ_HOME"; \ 233 | tar --extract --file "$RABBITMQ_PATH.tar.xz" --directory "$RABBITMQ_HOME" --strip-components 1; \ 234 | rm -rf "$RABBITMQ_PATH"*; \ 235 | # Do not default SYS_PREFIX to RABBITMQ_HOME, leave it empty 236 | grep -qE '^SYS_PREFIX=\$\{RABBITMQ_HOME\}$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 237 | sed -i 's/^SYS_PREFIX=.*$/SYS_PREFIX=/' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 238 | grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 239 | chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ 240 | \ 241 | apt-mark auto '.*' > /dev/null; \ 242 | apt-mark manual $savedAptMark; \ 243 | apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ 244 | \ 245 | # verify assumption of no stale cookies 246 | [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ 247 | # Ensure RabbitMQ was installed correctly by running a few commands that do not depend on a running server, as the rabbitmq user 248 | # If they all succeed, it's safe to assume that things have been set up correctly 249 | gosu rabbitmq rabbitmqctl help; \ 250 | gosu rabbitmq rabbitmqctl list_ciphers; \ 251 | gosu rabbitmq rabbitmq-plugins list; \ 252 | # no stale cookies 253 | rm "$RABBITMQ_DATA_DIR/.erlang.cookie" 254 | 255 | # Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) 256 | RUN set -eux; \ 257 | rabbitmq-plugins enable --offline rabbitmq_prometheus; \ 258 | echo 'management_agent.disable_metrics_collector = true' > /etc/rabbitmq/conf.d/management_agent.disable_metrics_collector.conf 259 | 260 | # Added for backwards compatibility - users can simply COPY custom plugins to /plugins 261 | RUN ln -sf /opt/rabbitmq/plugins /plugins 262 | 263 | # set home so that any `--user` knows where to put the erlang cookie 264 | ENV HOME $RABBITMQ_DATA_DIR 265 | # Hint that the data (a.k.a. home dir) dir should be separate volume 266 | VOLUME $RABBITMQ_DATA_DIR 267 | 268 | # 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) 269 | # 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 270 | # https://docs.docker.com/samples/library/ubuntu/#locales 271 | ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 272 | 273 | COPY docker-entrypoint.sh /usr/local/bin/ 274 | ENTRYPOINT ["docker-entrypoint.sh"] 275 | 276 | EXPOSE 4369 5671 5672 15691 15692 25672 277 | CMD ["rabbitmq-server"] 278 | -------------------------------------------------------------------------------- /3.8-rc/ubuntu/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eu 3 | 4 | # usage: file_env VAR [DEFAULT] 5 | # ie: file_env 'XYZ_DB_PASSWORD' 'example' 6 | # (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of 7 | # "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) 8 | file_env() { 9 | local var="$1" 10 | local fileVar="${var}_FILE" 11 | local def="${2:-}" 12 | if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then 13 | echo >&2 "error: both $var and $fileVar are set (but are exclusive)" 14 | exit 1 15 | fi 16 | local val="$def" 17 | if [ "${!var:-}" ]; then 18 | val="${!var}" 19 | elif [ "${!fileVar:-}" ]; then 20 | val="$(< "${!fileVar}")" 21 | fi 22 | export "$var"="$val" 23 | unset "$fileVar" 24 | } 25 | 26 | # backwards compatibility for old environment variables 27 | : "${RABBITMQ_SSL_CERTFILE:=${RABBITMQ_SSL_CERT_FILE:-}}" 28 | : "${RABBITMQ_SSL_KEYFILE:=${RABBITMQ_SSL_KEY_FILE:-}}" 29 | : "${RABBITMQ_SSL_CACERTFILE:=${RABBITMQ_SSL_CA_FILE:-}}" 30 | 31 | # "management" SSL config should default to using the same certs 32 | : "${RABBITMQ_MANAGEMENT_SSL_CACERTFILE:=$RABBITMQ_SSL_CACERTFILE}" 33 | : "${RABBITMQ_MANAGEMENT_SSL_CERTFILE:=$RABBITMQ_SSL_CERTFILE}" 34 | : "${RABBITMQ_MANAGEMENT_SSL_KEYFILE:=$RABBITMQ_SSL_KEYFILE}" 35 | 36 | # Allowed env vars that will be read from mounted files (i.e. Docker Secrets): 37 | fileEnvKeys=( 38 | default_user 39 | default_pass 40 | ) 41 | 42 | # https://www.rabbitmq.com/configure.html 43 | sslConfigKeys=( 44 | cacertfile 45 | certfile 46 | depth 47 | fail_if_no_peer_cert 48 | keyfile 49 | verify 50 | ) 51 | managementConfigKeys=( 52 | "${sslConfigKeys[@]/#/ssl_}" 53 | ) 54 | rabbitConfigKeys=( 55 | default_pass 56 | default_user 57 | default_vhost 58 | vm_memory_high_watermark 59 | ) 60 | fileConfigKeys=( 61 | management_ssl_cacertfile 62 | management_ssl_certfile 63 | management_ssl_keyfile 64 | ssl_cacertfile 65 | ssl_certfile 66 | ssl_keyfile 67 | ) 68 | allConfigKeys=( 69 | "${managementConfigKeys[@]/#/management_}" 70 | "${rabbitConfigKeys[@]}" 71 | "${sslConfigKeys[@]/#/ssl_}" 72 | ) 73 | 74 | declare -A configDefaults=( 75 | [management_ssl_fail_if_no_peer_cert]='false' 76 | [management_ssl_verify]='verify_none' 77 | 78 | [ssl_fail_if_no_peer_cert]='true' 79 | [ssl_verify]='verify_peer' 80 | ) 81 | 82 | # allow the container to be started with `--user` 83 | if [[ "$1" == rabbitmq* ]] && [ "$(id -u)" = '0' ]; then 84 | # this needs to happen late enough that we have the SSL config 85 | # https://github.com/docker-library/rabbitmq/issues/283 86 | for conf in "${allConfigKeys[@]}"; do 87 | var="RABBITMQ_${conf^^}" 88 | val="${!var:-}" 89 | [ -n "$val" ] || continue 90 | case "$conf" in 91 | *_ssl_*file | ssl_*file ) 92 | if [ -f "$val" ] && ! gosu rabbitmq test -r "$val"; then 93 | newFile="/tmp/rabbitmq-ssl/$conf.pem" 94 | echo >&2 95 | echo >&2 "WARNING: '$val' ($var) is not readable by rabbitmq ($(id rabbitmq)); copying to '$newFile'" 96 | echo >&2 97 | cat "$val" > "$newFile" 98 | chown rabbitmq "$newFile" 99 | chmod 0400 "$newFile" 100 | eval 'export '$var'="$newFile"' 101 | fi 102 | ;; 103 | esac 104 | done 105 | 106 | if [ "$1" = 'rabbitmq-server' ]; then 107 | find /var/lib/rabbitmq \! -user rabbitmq -exec chown rabbitmq '{}' + 108 | fi 109 | 110 | exec gosu rabbitmq "$BASH_SOURCE" "$@" 111 | fi 112 | 113 | haveConfig= 114 | haveSslConfig= 115 | haveManagementSslConfig= 116 | for fileEnvKey in "${fileEnvKeys[@]}"; do file_env "RABBITMQ_${fileEnvKey^^}"; done 117 | for conf in "${allConfigKeys[@]}"; do 118 | var="RABBITMQ_${conf^^}" 119 | val="${!var:-}" 120 | if [ "$val" ]; then 121 | if [ "${configDefaults[$conf]:-}" ] && [ "${configDefaults[$conf]}" = "$val" ]; then 122 | # if the value set is the same as the default, treat it as if it isn't set 123 | continue 124 | fi 125 | haveConfig=1 126 | case "$conf" in 127 | ssl_*) haveSslConfig=1 ;; 128 | management_ssl_*) haveManagementSslConfig=1 ;; 129 | esac 130 | fi 131 | done 132 | if [ "$haveSslConfig" ]; then 133 | missing=() 134 | for sslConf in cacertfile certfile keyfile; do 135 | var="RABBITMQ_SSL_${sslConf^^}" 136 | val="${!var}" 137 | if [ -z "$val" ]; then 138 | missing+=( "$var" ) 139 | fi 140 | done 141 | if [ "${#missing[@]}" -gt 0 ]; then 142 | { 143 | echo 144 | echo 'error: SSL requested, but missing required configuration' 145 | for miss in "${missing[@]}"; do 146 | echo " - $miss" 147 | done 148 | echo 149 | } >&2 150 | exit 1 151 | fi 152 | fi 153 | missingFiles=() 154 | for conf in "${fileConfigKeys[@]}"; do 155 | var="RABBITMQ_${conf^^}" 156 | val="${!var}" 157 | if [ "$val" ] && [ ! -f "$val" ]; then 158 | missingFiles+=( "$val ($var)" ) 159 | fi 160 | done 161 | if [ "${#missingFiles[@]}" -gt 0 ]; then 162 | { 163 | echo 164 | echo 'error: files specified, but missing' 165 | for miss in "${missingFiles[@]}"; do 166 | echo " - $miss" 167 | done 168 | echo 169 | } >&2 170 | exit 1 171 | fi 172 | 173 | # set defaults for missing values (but only after we're done with all our checking so we don't throw any of that off) 174 | for conf in "${!configDefaults[@]}"; do 175 | default="${configDefaults[$conf]}" 176 | var="RABBITMQ_${conf^^}" 177 | [ -z "${!var:-}" ] || continue 178 | eval "export $var=\"\$default\"" 179 | done 180 | 181 | # if long and short hostnames are not the same, use long hostnames 182 | if [ "$(hostname)" != "$(hostname -s)" ]; then 183 | : "${RABBITMQ_USE_LONGNAME:=true}" 184 | fi 185 | 186 | if [ "${RABBITMQ_ERLANG_COOKIE:-}" ]; then 187 | cookieFile='/var/lib/rabbitmq/.erlang.cookie' 188 | if [ -e "$cookieFile" ]; then 189 | if [ "$(cat "$cookieFile" 2>/dev/null)" != "$RABBITMQ_ERLANG_COOKIE" ]; then 190 | echo >&2 191 | echo >&2 "warning: $cookieFile contents do not match RABBITMQ_ERLANG_COOKIE" 192 | echo >&2 193 | fi 194 | else 195 | echo "$RABBITMQ_ERLANG_COOKIE" > "$cookieFile" 196 | fi 197 | chmod 600 "$cookieFile" 198 | fi 199 | 200 | configBase="${RABBITMQ_CONFIG_FILE:-/etc/rabbitmq/rabbitmq}" 201 | oldConfigFile="$configBase.config" 202 | newConfigFile="$configBase.conf" 203 | 204 | shouldWriteConfig="$haveConfig" 205 | if [ -n "$shouldWriteConfig" ] && ! touch "$newConfigFile"; then 206 | # config file exists but it isn't writeable (likely read-only mount, such as Kubernetes configMap) 207 | export RABBITMQ_CONFIG_FILE='/tmp/rabbitmq.conf' 208 | cp "$newConfigFile" "$RABBITMQ_CONFIG_FILE" 209 | echo >&2 210 | echo >&2 "WARNING: '$newConfigFile' is not writable, but environment variables have been provided which request that we write to it" 211 | echo >&2 " We have copied it to '$RABBITMQ_CONFIG_FILE' so it can be amended to work around the problem, but it is recommended that the read-only source file should be modified and the environment variables removed instead." 212 | echo >&2 213 | newConfigFile="$RABBITMQ_CONFIG_FILE" 214 | fi 215 | if [ -n "$shouldWriteConfig" ] && [ -f "$oldConfigFile" ]; then 216 | { 217 | echo "error: Docker configuration environment variables specified, but old-style (Erlang syntax) configuration file '$oldConfigFile' exists" 218 | echo " Suggested fixes: (choose one)" 219 | echo " - remove '$oldConfigFile'" 220 | echo " - remove any Docker-specific 'RABBITMQ_...' environment variables" 221 | echo " - convert '$oldConfigFile' to the newer sysctl format ('$newConfigFile'); see https://www.rabbitmq.com/configure.html#config-file" 222 | } >&2 223 | exit 1 224 | fi 225 | if [ -z "$shouldWriteConfig" ] && [ ! -f "$oldConfigFile" ] && [ ! -f "$newConfigFile" ]; then 226 | # no config files, we should write one 227 | shouldWriteConfig=1 228 | fi 229 | 230 | # http://stackoverflow.com/a/2705678/433558 231 | sed_escape_lhs() { 232 | echo "$@" | sed -e 's/[]\/$*.^|[]/\\&/g' 233 | } 234 | sed_escape_rhs() { 235 | echo "$@" | sed -e 's/[\/&]/\\&/g' 236 | } 237 | rabbit_set_config() { 238 | local key="$1"; shift 239 | local val="$1"; shift 240 | 241 | [ -e "$newConfigFile" ] || touch "$newConfigFile" 242 | 243 | local sedKey="$(sed_escape_lhs "$key")" 244 | local sedVal="$(sed_escape_rhs "$val")" 245 | sed -ri \ 246 | "s/^[[:space:]]*(${sedKey}[[:space:]]*=[[:space:]]*)\S.*\$/\1${sedVal}/" \ 247 | "$newConfigFile" 248 | if ! grep -qE "^${sedKey}[[:space:]]*=" "$newConfigFile"; then 249 | sed -i -e '$a\' "$newConfigFile" # https://github.com/docker-library/rabbitmq/issues/456#issuecomment-752251872 (https://unix.stackexchange.com/a/31955/153467) 250 | echo "$key = $val" >> "$newConfigFile" 251 | fi 252 | } 253 | rabbit_comment_config() { 254 | local key="$1"; shift 255 | 256 | [ -e "$newConfigFile" ] || touch "$newConfigFile" 257 | 258 | local sedKey="$(sed_escape_lhs "$key")" 259 | sed -ri \ 260 | "s/^[[:space:]]*#?[[:space:]]*(${sedKey}[[:space:]]*=[[:space:]]*\S.*)\$/# \1/" \ 261 | "$newConfigFile" 262 | } 263 | rabbit_env_config() { 264 | local prefix="$1"; shift 265 | 266 | local conf 267 | for conf; do 268 | local var="rabbitmq${prefix:+_$prefix}_$conf" 269 | var="${var^^}" 270 | 271 | local key="$conf" 272 | case "$prefix" in 273 | ssl) key="ssl_options.$key" ;; 274 | management_ssl) key="management.ssl.$key" ;; 275 | esac 276 | 277 | local val="${!var:-}" 278 | local rawVal="$val" 279 | case "$conf" in 280 | fail_if_no_peer_cert) 281 | case "${val,,}" in 282 | false|no|0|'') rawVal='false' ;; 283 | true|yes|1|*) rawVal='true' ;; 284 | esac 285 | ;; 286 | 287 | vm_memory_high_watermark) continue ;; # handled separately 288 | esac 289 | 290 | if [ -n "$rawVal" ]; then 291 | rabbit_set_config "$key" "$rawVal" 292 | else 293 | rabbit_comment_config "$key" 294 | fi 295 | done 296 | } 297 | 298 | if [ "$1" = 'rabbitmq-server' ] && [ "$shouldWriteConfig" ]; then 299 | rabbit_set_config 'loopback_users.guest' 'false' 300 | 301 | # determine whether to set "vm_memory_high_watermark" (based on cgroups) 302 | memTotalKb= 303 | if [ -r /proc/meminfo ]; then 304 | memTotalKb="$(awk -F ':? +' '$1 == "MemTotal" { print $2; exit }' /proc/meminfo)" 305 | fi 306 | memLimitB= 307 | if [ -r /sys/fs/cgroup/memory/memory.limit_in_bytes ]; then 308 | # "18446744073709551615" is a valid value for "memory.limit_in_bytes", which is too big for Bash math to handle 309 | # "$(( 18446744073709551615 / 1024 ))" = 0; "$(( 18446744073709551615 * 40 / 100 ))" = 0 310 | memLimitB="$(awk -v totKb="$memTotalKb" '{ 311 | limB = $0; 312 | limKb = limB / 1024; 313 | if (!totKb || limKb < totKb) { 314 | printf "%.0f\n", limB; 315 | } 316 | }' /sys/fs/cgroup/memory/memory.limit_in_bytes)" 317 | fi 318 | if [ -n "$memLimitB" ]; then 319 | # if we have a cgroup memory limit, let's inform RabbitMQ of what it is (so it can calculate vm_memory_high_watermark properly) 320 | # https://github.com/rabbitmq/rabbitmq-server/pull/1234 321 | rabbit_set_config 'total_memory_available_override_value' "$memLimitB" 322 | fi 323 | # https://www.rabbitmq.com/memory.html#memsup-usage 324 | if [ "${RABBITMQ_VM_MEMORY_HIGH_WATERMARK:-}" ]; then 325 | # https://github.com/docker-library/rabbitmq/pull/105#issuecomment-242165822 326 | vmMemoryHighWatermark="$( 327 | echo "$RABBITMQ_VM_MEMORY_HIGH_WATERMARK" | awk ' 328 | /^[0-9]*[.][0-9]+$|^[0-9]+([.][0-9]+)?%$/ { 329 | perc = $0; 330 | if (perc ~ /%$/) { 331 | gsub(/%$/, "", perc); 332 | perc = perc / 100; 333 | } 334 | if (perc > 1.0 || perc < 0.0) { 335 | printf "error: invalid percentage for vm_memory_high_watermark: %s (must be >= 0%%, <= 100%%)\n", $0 > "/dev/stderr"; 336 | exit 1; 337 | } 338 | printf "vm_memory_high_watermark.relative %0.03f\n", perc; 339 | next; 340 | } 341 | /^[0-9]+$/ { 342 | printf "vm_memory_high_watermark.absolute %s\n", $0; 343 | next; 344 | } 345 | /^[0-9]+([.][0-9]+)?[a-zA-Z]+$/ { 346 | printf "vm_memory_high_watermark.absolute %s\n", $0; 347 | next; 348 | } 349 | { 350 | printf "error: unexpected input for vm_memory_high_watermark: %s\n", $0; 351 | exit 1; 352 | } 353 | ' 354 | )" 355 | if [ "$vmMemoryHighWatermark" ]; then 356 | vmMemoryHighWatermarkKey="${vmMemoryHighWatermark%% *}" 357 | vmMemoryHighWatermarkVal="${vmMemoryHighWatermark#$vmMemoryHighWatermarkKey }" 358 | rabbit_set_config "$vmMemoryHighWatermarkKey" "$vmMemoryHighWatermarkVal" 359 | case "$vmMemoryHighWatermarkKey" in 360 | # make sure we only set one or the other 361 | 'vm_memory_high_watermark.absolute') rabbit_comment_config 'vm_memory_high_watermark.relative' ;; 362 | 'vm_memory_high_watermark.relative') rabbit_comment_config 'vm_memory_high_watermark.absolute' ;; 363 | esac 364 | fi 365 | fi 366 | 367 | if [ "$haveSslConfig" ]; then 368 | rabbit_set_config 'listeners.ssl.default' 5671 369 | rabbit_env_config 'ssl' "${sslConfigKeys[@]}" 370 | else 371 | rabbit_set_config 'listeners.tcp.default' 5672 372 | fi 373 | 374 | rabbit_env_config '' "${rabbitConfigKeys[@]}" 375 | 376 | # if management plugin is installed, generate config for it 377 | # https://www.rabbitmq.com/management.html#configuration 378 | if [ "$(rabbitmq-plugins list -q -m -e rabbitmq_management)" ]; then 379 | if [ "$haveManagementSslConfig" ]; then 380 | rabbit_set_config 'management.ssl.port' 15671 381 | rabbit_env_config 'management_ssl' "${sslConfigKeys[@]}" 382 | else 383 | rabbit_set_config 'management.tcp.port' 15672 384 | fi 385 | 386 | # if definitions file exists, then load it 387 | # https://www.rabbitmq.com/management.html#load-definitions 388 | managementDefinitionsFile='/etc/rabbitmq/definitions.json' 389 | if [ -f "$managementDefinitionsFile" ]; then 390 | # We use `load_definitions` (the built-in setting as of 3.8.2+) instead 391 | # of `management.load_definitions`. 392 | # See https://github.com/docker-library/rabbitmq/issues/429 for details. 393 | rabbit_set_config 'load_definitions' "$managementDefinitionsFile" 394 | fi 395 | fi 396 | fi 397 | 398 | combinedSsl='/tmp/rabbitmq-ssl/combined.pem' 399 | if [ "$haveSslConfig" ] && [[ "$1" == rabbitmq* ]] && [ ! -f "$combinedSsl" ]; then 400 | # Create combined cert 401 | { 402 | cat "$RABBITMQ_SSL_CERTFILE" 403 | echo # https://github.com/docker-library/rabbitmq/issues/357#issuecomment-517755647 404 | cat "$RABBITMQ_SSL_KEYFILE" 405 | } > "$combinedSsl" 406 | chmod 0400 "$combinedSsl" 407 | fi 408 | if [ "$haveSslConfig" ] && [ -f "$combinedSsl" ]; then 409 | # More ENV vars for make clustering happiness 410 | # we don't handle clustering in this script, but these args should ensure 411 | # clustered SSL-enabled members will talk nicely 412 | export ERL_SSL_PATH="$(erl -eval 'io:format("~p", [code:lib_dir(ssl, ebin)]),halt().' -noshell)" 413 | sslErlArgs="-pa $ERL_SSL_PATH -proto_dist inet_tls -ssl_dist_opt server_certfile $combinedSsl -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true" 414 | export RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="${RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS:-} $sslErlArgs" 415 | export RABBITMQ_CTL_ERL_ARGS="${RABBITMQ_CTL_ERL_ARGS:-} $sslErlArgs" 416 | fi 417 | 418 | exec "$@" 419 | -------------------------------------------------------------------------------- /3.8-rc/ubuntu/management/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM rabbitmq:3.8-rc 8 | 9 | RUN rabbitmq-plugins enable --offline rabbitmq_management 10 | 11 | # make sure the metrics collector is re-enabled (disabled in the base image for Prometheus-style metrics by default) 12 | RUN rm -f /etc/rabbitmq/conf.d/management_agent.disable_metrics_collector.conf 13 | 14 | # extract "rabbitmqadmin" from inside the "rabbitmq_management-X.Y.Z.ez" plugin zipfile 15 | # see https://github.com/docker-library/rabbitmq/issues/207 16 | RUN set -eux; \ 17 | erl -noinput -eval ' \ 18 | { ok, AdminBin } = zip:foldl(fun(FileInArchive, GetInfo, GetBin, Acc) -> \ 19 | case Acc of \ 20 | "" -> \ 21 | case lists:suffix("/rabbitmqadmin", FileInArchive) of \ 22 | true -> GetBin(); \ 23 | false -> Acc \ 24 | end; \ 25 | _ -> Acc \ 26 | end \ 27 | end, "", init:get_plain_arguments()), \ 28 | io:format("~s", [ AdminBin ]), \ 29 | init:stop(). \ 30 | ' -- /plugins/rabbitmq_management-*.ez > /usr/local/bin/rabbitmqadmin; \ 31 | [ -s /usr/local/bin/rabbitmqadmin ]; \ 32 | chmod +x /usr/local/bin/rabbitmqadmin; \ 33 | apt-get update; \ 34 | apt-get install -y --no-install-recommends python3; \ 35 | rm -rf /var/lib/apt/lists/*; \ 36 | rabbitmqadmin --version 37 | 38 | EXPOSE 15671 15672 39 | -------------------------------------------------------------------------------- /3.8/alpine/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | # Alpine Linux is not officially supported by the RabbitMQ team -- use at your own risk! 8 | FROM alpine:3.13 9 | 10 | RUN apk add --no-cache \ 11 | # grab su-exec for easy step-down from root 12 | 'su-exec>=0.2' \ 13 | # bash for docker-entrypoint.sh 14 | bash \ 15 | # "ps" for "rabbitmqctl wait" (https://github.com/docker-library/rabbitmq/issues/162) 16 | procps 17 | 18 | # Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally 19 | ARG PGP_KEYSERVER=ha.pool.sks-keyservers.net 20 | # If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, 21 | # run the build with a different PGP_KEYSERVER, e.g. docker build --tag rabbitmq:3.8 --build-arg PGP_KEYSERVER=pgpkeys.eu 3.8/ubuntu 22 | # For context, see https://github.com/docker-library/official-images/issues/4252 23 | 24 | ENV OPENSSL_VERSION 1.1.1j 25 | ENV OPENSSL_SOURCE_SHA256="aaf2fcb575cdf6491b98ab4829abf78a3dec8402b8b81efc8f23c00d443981bf" 26 | # https://www.openssl.org/community/omc.html 27 | ENV OPENSSL_PGP_KEY_IDS="0x8657ABB260F056B1E5190839D9C4D26D0E604491 0x5B2545DAB21995F4088CEFAA36CEE4DEB00CFE33 0xED230BEC4D4F2518B9D7DF41F0DB4D21C1D35231 0xC1F33DD8CE1D4CC613AF14DA9195C48241FBF7DD 0x7953AC1FBC3DC8B3B292393ED5E9E43F7DF9EE8C 0xE5E52560DD91C556DDBDA5D02064C53641C25E5D" 28 | 29 | ENV OTP_VERSION 23.2.5 30 | # TODO add PGP checking when the feature will be added to Erlang/OTP's build system 31 | # https://erlang.org/pipermail/erlang-questions/2019-January/097067.html 32 | ENV OTP_SOURCE_SHA256="0b1ca7d60f4f5a70b56cd0bef77cec2087a53a9a1812d5276a8cd4ce1acfa962" 33 | 34 | # Install dependencies required to build Erlang/OTP from source 35 | # https://erlang.org/doc/installation_guide/INSTALL.html 36 | # autoconf: Required to configure Erlang/OTP before compiling 37 | # dpkg-dev: Required to set up host & build type when compiling Erlang/OTP 38 | # gnupg: Required to verify OpenSSL artefacts 39 | # libncurses5-dev: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli 40 | RUN set -eux; \ 41 | \ 42 | apk add --no-cache --virtual .build-deps \ 43 | autoconf \ 44 | dpkg-dev dpkg \ 45 | gcc \ 46 | gnupg \ 47 | libc-dev \ 48 | linux-headers \ 49 | make \ 50 | ncurses-dev \ 51 | ; \ 52 | \ 53 | OPENSSL_SOURCE_URL="https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz"; \ 54 | OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ 55 | OPENSSL_CONFIG_DIR=/usr/local/etc/ssl; \ 56 | \ 57 | # /usr/local/src doesn't exist in Alpine by default 58 | mkdir /usr/local/src; \ 59 | \ 60 | # Required by the crypto & ssl Erlang/OTP applications 61 | wget --output-document "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_SOURCE_URL.asc"; \ 62 | wget --output-document "$OPENSSL_PATH.tar.gz" "$OPENSSL_SOURCE_URL"; \ 63 | export GNUPGHOME="$(mktemp -d)"; \ 64 | for key in $OPENSSL_PGP_KEY_IDS; do \ 65 | gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \ 66 | done; \ 67 | gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \ 68 | gpgconf --kill all; \ 69 | rm -rf "$GNUPGHOME"; \ 70 | echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum -c -; \ 71 | mkdir -p "$OPENSSL_PATH"; \ 72 | tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \ 73 | \ 74 | # Configure OpenSSL for compilation 75 | cd "$OPENSSL_PATH"; \ 76 | # OpenSSL's "config" script uses a lot of "uname"-based target detection... 77 | MACHINE="$(dpkg-architecture --query DEB_BUILD_GNU_CPU)" \ 78 | RELEASE="4.x.y-z" \ 79 | SYSTEM='Linux' \ 80 | BUILD='???' \ 81 | ./config \ 82 | --openssldir="$OPENSSL_CONFIG_DIR" \ 83 | # 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) 84 | -Wl,-rpath=/usr/local/lib \ 85 | ; \ 86 | # Compile, install OpenSSL, verify that the command-line works & development headers are present 87 | make -j "$(getconf _NPROCESSORS_ONLN)"; \ 88 | make install_sw install_ssldirs; \ 89 | cd ..; \ 90 | rm -rf "$OPENSSL_PATH"*; \ 91 | # use Alpine's CA certificates 92 | rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ 93 | ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR"; \ 94 | # smoke test 95 | openssl version; \ 96 | \ 97 | OTP_SOURCE_URL="https://github.com/erlang/otp/releases/download/OTP-$OTP_VERSION/otp_src_$OTP_VERSION.tar.gz"; \ 98 | OTP_PATH="/usr/local/src/otp-$OTP_VERSION"; \ 99 | \ 100 | # Download, verify & extract OTP_SOURCE 101 | mkdir -p "$OTP_PATH"; \ 102 | wget --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \ 103 | echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum -c -; \ 104 | tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \ 105 | \ 106 | # Configure Erlang/OTP for compilation, disable unused features & applications 107 | # https://erlang.org/doc/applications.html 108 | # ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation 109 | cd "$OTP_PATH"; \ 110 | export ERL_TOP="$OTP_PATH"; \ 111 | ./otp_build autoconf; \ 112 | export CFLAGS='-g -O2'; \ 113 | # 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) 114 | export CFLAGS="$CFLAGS -Wl,-rpath=/usr/local/lib"; \ 115 | hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ 116 | buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ 117 | dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ 118 | ./configure \ 119 | --host="$hostArch" \ 120 | --build="$buildArch" \ 121 | --disable-dynamic-ssl-lib \ 122 | --disable-hipe \ 123 | --disable-sctp \ 124 | --disable-silent-rules \ 125 | --enable-clock-gettime \ 126 | --enable-hybrid-heap \ 127 | --enable-kernel-poll \ 128 | --enable-shared-zlib \ 129 | --enable-smp-support \ 130 | --enable-threads \ 131 | --with-microstate-accounting=extra \ 132 | --without-common_test \ 133 | --without-debugger \ 134 | --without-dialyzer \ 135 | --without-diameter \ 136 | --without-edoc \ 137 | --without-erl_docgen \ 138 | --without-erl_interface \ 139 | --without-et \ 140 | --without-eunit \ 141 | --without-ftp \ 142 | --without-hipe \ 143 | --without-jinterface \ 144 | --without-megaco \ 145 | --without-observer \ 146 | --without-odbc \ 147 | --without-reltool \ 148 | --without-ssh \ 149 | --without-tftp \ 150 | --without-wx \ 151 | ; \ 152 | # Compile & install Erlang/OTP 153 | make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ 154 | make install; \ 155 | cd ..; \ 156 | rm -rf \ 157 | "$OTP_PATH"* \ 158 | /usr/local/lib/erlang/lib/*/examples \ 159 | /usr/local/lib/erlang/lib/*/src \ 160 | ; \ 161 | \ 162 | runDeps="$( \ 163 | scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ 164 | | tr ',' '\n' \ 165 | | sort -u \ 166 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 167 | )"; \ 168 | apk add --no-cache --virtual .otp-run-deps $runDeps; \ 169 | apk del --no-network .build-deps; \ 170 | \ 171 | # Check that OpenSSL still works after purging build dependencies 172 | openssl version; \ 173 | # Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly 174 | erl -noshell -eval 'io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' 175 | 176 | ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq 177 | # Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM 178 | RUN set -eux; \ 179 | addgroup -g 101 -S rabbitmq; \ 180 | adduser -u 100 -S -h "$RABBITMQ_DATA_DIR" -G rabbitmq rabbitmq; \ 181 | mkdir -p "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 182 | chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 183 | chmod 777 "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 184 | ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie 185 | 186 | # Use the latest stable RabbitMQ release (https://www.rabbitmq.com/download.html) 187 | ENV RABBITMQ_VERSION 3.8.12 188 | # https://www.rabbitmq.com/signatures.html#importing-gpg 189 | ENV RABBITMQ_PGP_KEY_ID="0x0A9AF2115F4687BD29803A206B73A36E6026DFCA" 190 | ENV RABBITMQ_HOME=/opt/rabbitmq 191 | 192 | # Add RabbitMQ to PATH, send all logs to TTY 193 | ENV PATH=$RABBITMQ_HOME/sbin:$PATH \ 194 | RABBITMQ_LOGS=- 195 | 196 | # Install RabbitMQ 197 | RUN set -eux; \ 198 | \ 199 | apk add --no-cache --virtual .build-deps \ 200 | gnupg \ 201 | xz \ 202 | ; \ 203 | \ 204 | RABBITMQ_SOURCE_URL="https://github.com/rabbitmq/rabbitmq-server/releases/download/v$RABBITMQ_VERSION/rabbitmq-server-generic-unix-latest-toolchain-$RABBITMQ_VERSION.tar.xz"; \ 205 | RABBITMQ_PATH="/usr/local/src/rabbitmq-$RABBITMQ_VERSION"; \ 206 | \ 207 | wget --output-document "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_SOURCE_URL.asc"; \ 208 | wget --output-document "$RABBITMQ_PATH.tar.xz" "$RABBITMQ_SOURCE_URL"; \ 209 | \ 210 | export GNUPGHOME="$(mktemp -d)"; \ 211 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$RABBITMQ_PGP_KEY_ID"; \ 212 | gpg --batch --verify "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_PATH.tar.xz"; \ 213 | gpgconf --kill all; \ 214 | rm -rf "$GNUPGHOME"; \ 215 | \ 216 | mkdir -p "$RABBITMQ_HOME"; \ 217 | tar --extract --file "$RABBITMQ_PATH.tar.xz" --directory "$RABBITMQ_HOME" --strip-components 1; \ 218 | rm -rf "$RABBITMQ_PATH"*; \ 219 | # Do not default SYS_PREFIX to RABBITMQ_HOME, leave it empty 220 | grep -qE '^SYS_PREFIX=\$\{RABBITMQ_HOME\}$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 221 | sed -i 's/^SYS_PREFIX=.*$/SYS_PREFIX=/' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 222 | grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 223 | chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ 224 | \ 225 | apk del .build-deps; \ 226 | \ 227 | # verify assumption of no stale cookies 228 | [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ 229 | # Ensure RabbitMQ was installed correctly by running a few commands that do not depend on a running server, as the rabbitmq user 230 | # If they all succeed, it's safe to assume that things have been set up correctly 231 | su-exec rabbitmq rabbitmqctl help; \ 232 | su-exec rabbitmq rabbitmqctl list_ciphers; \ 233 | su-exec rabbitmq rabbitmq-plugins list; \ 234 | # no stale cookies 235 | rm "$RABBITMQ_DATA_DIR/.erlang.cookie" 236 | 237 | # Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) 238 | RUN set -eux; \ 239 | rabbitmq-plugins enable --offline rabbitmq_prometheus; \ 240 | echo 'management_agent.disable_metrics_collector = true' > /etc/rabbitmq/conf.d/management_agent.disable_metrics_collector.conf 241 | 242 | # Added for backwards compatibility - users can simply COPY custom plugins to /plugins 243 | RUN ln -sf /opt/rabbitmq/plugins /plugins 244 | 245 | # set home so that any `--user` knows where to put the erlang cookie 246 | ENV HOME $RABBITMQ_DATA_DIR 247 | # Hint that the data (a.k.a. home dir) dir should be separate volume 248 | VOLUME $RABBITMQ_DATA_DIR 249 | 250 | # 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) 251 | # 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 252 | # https://docs.docker.com/samples/library/ubuntu/#locales 253 | ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 254 | 255 | COPY docker-entrypoint.sh /usr/local/bin/ 256 | ENTRYPOINT ["docker-entrypoint.sh"] 257 | 258 | EXPOSE 4369 5671 5672 15691 15692 25672 259 | CMD ["rabbitmq-server"] 260 | -------------------------------------------------------------------------------- /3.8/alpine/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eu 3 | 4 | # usage: file_env VAR [DEFAULT] 5 | # ie: file_env 'XYZ_DB_PASSWORD' 'example' 6 | # (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of 7 | # "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) 8 | file_env() { 9 | local var="$1" 10 | local fileVar="${var}_FILE" 11 | local def="${2:-}" 12 | if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then 13 | echo >&2 "error: both $var and $fileVar are set (but are exclusive)" 14 | exit 1 15 | fi 16 | local val="$def" 17 | if [ "${!var:-}" ]; then 18 | val="${!var}" 19 | elif [ "${!fileVar:-}" ]; then 20 | val="$(< "${!fileVar}")" 21 | fi 22 | export "$var"="$val" 23 | unset "$fileVar" 24 | } 25 | 26 | # backwards compatibility for old environment variables 27 | : "${RABBITMQ_SSL_CERTFILE:=${RABBITMQ_SSL_CERT_FILE:-}}" 28 | : "${RABBITMQ_SSL_KEYFILE:=${RABBITMQ_SSL_KEY_FILE:-}}" 29 | : "${RABBITMQ_SSL_CACERTFILE:=${RABBITMQ_SSL_CA_FILE:-}}" 30 | 31 | # "management" SSL config should default to using the same certs 32 | : "${RABBITMQ_MANAGEMENT_SSL_CACERTFILE:=$RABBITMQ_SSL_CACERTFILE}" 33 | : "${RABBITMQ_MANAGEMENT_SSL_CERTFILE:=$RABBITMQ_SSL_CERTFILE}" 34 | : "${RABBITMQ_MANAGEMENT_SSL_KEYFILE:=$RABBITMQ_SSL_KEYFILE}" 35 | 36 | # Allowed env vars that will be read from mounted files (i.e. Docker Secrets): 37 | fileEnvKeys=( 38 | default_user 39 | default_pass 40 | ) 41 | 42 | # https://www.rabbitmq.com/configure.html 43 | sslConfigKeys=( 44 | cacertfile 45 | certfile 46 | depth 47 | fail_if_no_peer_cert 48 | keyfile 49 | verify 50 | ) 51 | managementConfigKeys=( 52 | "${sslConfigKeys[@]/#/ssl_}" 53 | ) 54 | rabbitConfigKeys=( 55 | default_pass 56 | default_user 57 | default_vhost 58 | vm_memory_high_watermark 59 | ) 60 | fileConfigKeys=( 61 | management_ssl_cacertfile 62 | management_ssl_certfile 63 | management_ssl_keyfile 64 | ssl_cacertfile 65 | ssl_certfile 66 | ssl_keyfile 67 | ) 68 | allConfigKeys=( 69 | "${managementConfigKeys[@]/#/management_}" 70 | "${rabbitConfigKeys[@]}" 71 | "${sslConfigKeys[@]/#/ssl_}" 72 | ) 73 | 74 | declare -A configDefaults=( 75 | [management_ssl_fail_if_no_peer_cert]='false' 76 | [management_ssl_verify]='verify_none' 77 | 78 | [ssl_fail_if_no_peer_cert]='true' 79 | [ssl_verify]='verify_peer' 80 | ) 81 | 82 | # allow the container to be started with `--user` 83 | if [[ "$1" == rabbitmq* ]] && [ "$(id -u)" = '0' ]; then 84 | # this needs to happen late enough that we have the SSL config 85 | # https://github.com/docker-library/rabbitmq/issues/283 86 | for conf in "${allConfigKeys[@]}"; do 87 | var="RABBITMQ_${conf^^}" 88 | val="${!var:-}" 89 | [ -n "$val" ] || continue 90 | case "$conf" in 91 | *_ssl_*file | ssl_*file ) 92 | if [ -f "$val" ] && ! su-exec rabbitmq test -r "$val"; then 93 | newFile="/tmp/rabbitmq-ssl/$conf.pem" 94 | echo >&2 95 | echo >&2 "WARNING: '$val' ($var) is not readable by rabbitmq ($(id rabbitmq)); copying to '$newFile'" 96 | echo >&2 97 | cat "$val" > "$newFile" 98 | chown rabbitmq "$newFile" 99 | chmod 0400 "$newFile" 100 | eval 'export '$var'="$newFile"' 101 | fi 102 | ;; 103 | esac 104 | done 105 | 106 | if [ "$1" = 'rabbitmq-server' ]; then 107 | find /var/lib/rabbitmq \! -user rabbitmq -exec chown rabbitmq '{}' + 108 | fi 109 | 110 | exec su-exec rabbitmq "$BASH_SOURCE" "$@" 111 | fi 112 | 113 | haveConfig= 114 | haveSslConfig= 115 | haveManagementSslConfig= 116 | for fileEnvKey in "${fileEnvKeys[@]}"; do file_env "RABBITMQ_${fileEnvKey^^}"; done 117 | for conf in "${allConfigKeys[@]}"; do 118 | var="RABBITMQ_${conf^^}" 119 | val="${!var:-}" 120 | if [ "$val" ]; then 121 | if [ "${configDefaults[$conf]:-}" ] && [ "${configDefaults[$conf]}" = "$val" ]; then 122 | # if the value set is the same as the default, treat it as if it isn't set 123 | continue 124 | fi 125 | haveConfig=1 126 | case "$conf" in 127 | ssl_*) haveSslConfig=1 ;; 128 | management_ssl_*) haveManagementSslConfig=1 ;; 129 | esac 130 | fi 131 | done 132 | if [ "$haveSslConfig" ]; then 133 | missing=() 134 | for sslConf in cacertfile certfile keyfile; do 135 | var="RABBITMQ_SSL_${sslConf^^}" 136 | val="${!var}" 137 | if [ -z "$val" ]; then 138 | missing+=( "$var" ) 139 | fi 140 | done 141 | if [ "${#missing[@]}" -gt 0 ]; then 142 | { 143 | echo 144 | echo 'error: SSL requested, but missing required configuration' 145 | for miss in "${missing[@]}"; do 146 | echo " - $miss" 147 | done 148 | echo 149 | } >&2 150 | exit 1 151 | fi 152 | fi 153 | missingFiles=() 154 | for conf in "${fileConfigKeys[@]}"; do 155 | var="RABBITMQ_${conf^^}" 156 | val="${!var}" 157 | if [ "$val" ] && [ ! -f "$val" ]; then 158 | missingFiles+=( "$val ($var)" ) 159 | fi 160 | done 161 | if [ "${#missingFiles[@]}" -gt 0 ]; then 162 | { 163 | echo 164 | echo 'error: files specified, but missing' 165 | for miss in "${missingFiles[@]}"; do 166 | echo " - $miss" 167 | done 168 | echo 169 | } >&2 170 | exit 1 171 | fi 172 | 173 | # set defaults for missing values (but only after we're done with all our checking so we don't throw any of that off) 174 | for conf in "${!configDefaults[@]}"; do 175 | default="${configDefaults[$conf]}" 176 | var="RABBITMQ_${conf^^}" 177 | [ -z "${!var:-}" ] || continue 178 | eval "export $var=\"\$default\"" 179 | done 180 | 181 | # if long and short hostnames are not the same, use long hostnames 182 | if [ "$(hostname)" != "$(hostname -s)" ]; then 183 | : "${RABBITMQ_USE_LONGNAME:=true}" 184 | fi 185 | 186 | if [ "${RABBITMQ_ERLANG_COOKIE:-}" ]; then 187 | cookieFile='/var/lib/rabbitmq/.erlang.cookie' 188 | if [ -e "$cookieFile" ]; then 189 | if [ "$(cat "$cookieFile" 2>/dev/null)" != "$RABBITMQ_ERLANG_COOKIE" ]; then 190 | echo >&2 191 | echo >&2 "warning: $cookieFile contents do not match RABBITMQ_ERLANG_COOKIE" 192 | echo >&2 193 | fi 194 | else 195 | echo "$RABBITMQ_ERLANG_COOKIE" > "$cookieFile" 196 | fi 197 | chmod 600 "$cookieFile" 198 | fi 199 | 200 | configBase="${RABBITMQ_CONFIG_FILE:-/etc/rabbitmq/rabbitmq}" 201 | oldConfigFile="$configBase.config" 202 | newConfigFile="$configBase.conf" 203 | 204 | shouldWriteConfig="$haveConfig" 205 | if [ -n "$shouldWriteConfig" ] && ! touch "$newConfigFile"; then 206 | # config file exists but it isn't writeable (likely read-only mount, such as Kubernetes configMap) 207 | export RABBITMQ_CONFIG_FILE='/tmp/rabbitmq.conf' 208 | cp "$newConfigFile" "$RABBITMQ_CONFIG_FILE" 209 | echo >&2 210 | echo >&2 "WARNING: '$newConfigFile' is not writable, but environment variables have been provided which request that we write to it" 211 | echo >&2 " We have copied it to '$RABBITMQ_CONFIG_FILE' so it can be amended to work around the problem, but it is recommended that the read-only source file should be modified and the environment variables removed instead." 212 | echo >&2 213 | newConfigFile="$RABBITMQ_CONFIG_FILE" 214 | fi 215 | if [ -n "$shouldWriteConfig" ] && [ -f "$oldConfigFile" ]; then 216 | { 217 | echo "error: Docker configuration environment variables specified, but old-style (Erlang syntax) configuration file '$oldConfigFile' exists" 218 | echo " Suggested fixes: (choose one)" 219 | echo " - remove '$oldConfigFile'" 220 | echo " - remove any Docker-specific 'RABBITMQ_...' environment variables" 221 | echo " - convert '$oldConfigFile' to the newer sysctl format ('$newConfigFile'); see https://www.rabbitmq.com/configure.html#config-file" 222 | } >&2 223 | exit 1 224 | fi 225 | if [ -z "$shouldWriteConfig" ] && [ ! -f "$oldConfigFile" ] && [ ! -f "$newConfigFile" ]; then 226 | # no config files, we should write one 227 | shouldWriteConfig=1 228 | fi 229 | 230 | # http://stackoverflow.com/a/2705678/433558 231 | sed_escape_lhs() { 232 | echo "$@" | sed -e 's/[]\/$*.^|[]/\\&/g' 233 | } 234 | sed_escape_rhs() { 235 | echo "$@" | sed -e 's/[\/&]/\\&/g' 236 | } 237 | rabbit_set_config() { 238 | local key="$1"; shift 239 | local val="$1"; shift 240 | 241 | [ -e "$newConfigFile" ] || touch "$newConfigFile" 242 | 243 | local sedKey="$(sed_escape_lhs "$key")" 244 | local sedVal="$(sed_escape_rhs "$val")" 245 | sed -ri \ 246 | "s/^[[:space:]]*(${sedKey}[[:space:]]*=[[:space:]]*)\S.*\$/\1${sedVal}/" \ 247 | "$newConfigFile" 248 | if ! grep -qE "^${sedKey}[[:space:]]*=" "$newConfigFile"; then 249 | sed -i -e '$a\' "$newConfigFile" # https://github.com/docker-library/rabbitmq/issues/456#issuecomment-752251872 (https://unix.stackexchange.com/a/31955/153467) 250 | echo "$key = $val" >> "$newConfigFile" 251 | fi 252 | } 253 | rabbit_comment_config() { 254 | local key="$1"; shift 255 | 256 | [ -e "$newConfigFile" ] || touch "$newConfigFile" 257 | 258 | local sedKey="$(sed_escape_lhs "$key")" 259 | sed -ri \ 260 | "s/^[[:space:]]*#?[[:space:]]*(${sedKey}[[:space:]]*=[[:space:]]*\S.*)\$/# \1/" \ 261 | "$newConfigFile" 262 | } 263 | rabbit_env_config() { 264 | local prefix="$1"; shift 265 | 266 | local conf 267 | for conf; do 268 | local var="rabbitmq${prefix:+_$prefix}_$conf" 269 | var="${var^^}" 270 | 271 | local key="$conf" 272 | case "$prefix" in 273 | ssl) key="ssl_options.$key" ;; 274 | management_ssl) key="management.ssl.$key" ;; 275 | esac 276 | 277 | local val="${!var:-}" 278 | local rawVal="$val" 279 | case "$conf" in 280 | fail_if_no_peer_cert) 281 | case "${val,,}" in 282 | false|no|0|'') rawVal='false' ;; 283 | true|yes|1|*) rawVal='true' ;; 284 | esac 285 | ;; 286 | 287 | vm_memory_high_watermark) continue ;; # handled separately 288 | esac 289 | 290 | if [ -n "$rawVal" ]; then 291 | rabbit_set_config "$key" "$rawVal" 292 | else 293 | rabbit_comment_config "$key" 294 | fi 295 | done 296 | } 297 | 298 | if [ "$1" = 'rabbitmq-server' ] && [ "$shouldWriteConfig" ]; then 299 | rabbit_set_config 'loopback_users.guest' 'false' 300 | 301 | # determine whether to set "vm_memory_high_watermark" (based on cgroups) 302 | memTotalKb= 303 | if [ -r /proc/meminfo ]; then 304 | memTotalKb="$(awk -F ':? +' '$1 == "MemTotal" { print $2; exit }' /proc/meminfo)" 305 | fi 306 | memLimitB= 307 | if [ -r /sys/fs/cgroup/memory/memory.limit_in_bytes ]; then 308 | # "18446744073709551615" is a valid value for "memory.limit_in_bytes", which is too big for Bash math to handle 309 | # "$(( 18446744073709551615 / 1024 ))" = 0; "$(( 18446744073709551615 * 40 / 100 ))" = 0 310 | memLimitB="$(awk -v totKb="$memTotalKb" '{ 311 | limB = $0; 312 | limKb = limB / 1024; 313 | if (!totKb || limKb < totKb) { 314 | printf "%.0f\n", limB; 315 | } 316 | }' /sys/fs/cgroup/memory/memory.limit_in_bytes)" 317 | fi 318 | if [ -n "$memLimitB" ]; then 319 | # if we have a cgroup memory limit, let's inform RabbitMQ of what it is (so it can calculate vm_memory_high_watermark properly) 320 | # https://github.com/rabbitmq/rabbitmq-server/pull/1234 321 | rabbit_set_config 'total_memory_available_override_value' "$memLimitB" 322 | fi 323 | # https://www.rabbitmq.com/memory.html#memsup-usage 324 | if [ "${RABBITMQ_VM_MEMORY_HIGH_WATERMARK:-}" ]; then 325 | # https://github.com/docker-library/rabbitmq/pull/105#issuecomment-242165822 326 | vmMemoryHighWatermark="$( 327 | echo "$RABBITMQ_VM_MEMORY_HIGH_WATERMARK" | awk ' 328 | /^[0-9]*[.][0-9]+$|^[0-9]+([.][0-9]+)?%$/ { 329 | perc = $0; 330 | if (perc ~ /%$/) { 331 | gsub(/%$/, "", perc); 332 | perc = perc / 100; 333 | } 334 | if (perc > 1.0 || perc < 0.0) { 335 | printf "error: invalid percentage for vm_memory_high_watermark: %s (must be >= 0%%, <= 100%%)\n", $0 > "/dev/stderr"; 336 | exit 1; 337 | } 338 | printf "vm_memory_high_watermark.relative %0.03f\n", perc; 339 | next; 340 | } 341 | /^[0-9]+$/ { 342 | printf "vm_memory_high_watermark.absolute %s\n", $0; 343 | next; 344 | } 345 | /^[0-9]+([.][0-9]+)?[a-zA-Z]+$/ { 346 | printf "vm_memory_high_watermark.absolute %s\n", $0; 347 | next; 348 | } 349 | { 350 | printf "error: unexpected input for vm_memory_high_watermark: %s\n", $0; 351 | exit 1; 352 | } 353 | ' 354 | )" 355 | if [ "$vmMemoryHighWatermark" ]; then 356 | vmMemoryHighWatermarkKey="${vmMemoryHighWatermark%% *}" 357 | vmMemoryHighWatermarkVal="${vmMemoryHighWatermark#$vmMemoryHighWatermarkKey }" 358 | rabbit_set_config "$vmMemoryHighWatermarkKey" "$vmMemoryHighWatermarkVal" 359 | case "$vmMemoryHighWatermarkKey" in 360 | # make sure we only set one or the other 361 | 'vm_memory_high_watermark.absolute') rabbit_comment_config 'vm_memory_high_watermark.relative' ;; 362 | 'vm_memory_high_watermark.relative') rabbit_comment_config 'vm_memory_high_watermark.absolute' ;; 363 | esac 364 | fi 365 | fi 366 | 367 | if [ "$haveSslConfig" ]; then 368 | rabbit_set_config 'listeners.ssl.default' 5671 369 | rabbit_env_config 'ssl' "${sslConfigKeys[@]}" 370 | else 371 | rabbit_set_config 'listeners.tcp.default' 5672 372 | fi 373 | 374 | rabbit_env_config '' "${rabbitConfigKeys[@]}" 375 | 376 | # if management plugin is installed, generate config for it 377 | # https://www.rabbitmq.com/management.html#configuration 378 | if [ "$(rabbitmq-plugins list -q -m -e rabbitmq_management)" ]; then 379 | if [ "$haveManagementSslConfig" ]; then 380 | rabbit_set_config 'management.ssl.port' 15671 381 | rabbit_env_config 'management_ssl' "${sslConfigKeys[@]}" 382 | else 383 | rabbit_set_config 'management.tcp.port' 15672 384 | fi 385 | 386 | # if definitions file exists, then load it 387 | # https://www.rabbitmq.com/management.html#load-definitions 388 | managementDefinitionsFile='/etc/rabbitmq/definitions.json' 389 | if [ -f "$managementDefinitionsFile" ]; then 390 | # We use `load_definitions` (the built-in setting as of 3.8.2+) instead 391 | # of `management.load_definitions`. 392 | # See https://github.com/docker-library/rabbitmq/issues/429 for details. 393 | rabbit_set_config 'load_definitions' "$managementDefinitionsFile" 394 | fi 395 | fi 396 | fi 397 | 398 | combinedSsl='/tmp/rabbitmq-ssl/combined.pem' 399 | if [ "$haveSslConfig" ] && [[ "$1" == rabbitmq* ]] && [ ! -f "$combinedSsl" ]; then 400 | # Create combined cert 401 | { 402 | cat "$RABBITMQ_SSL_CERTFILE" 403 | echo # https://github.com/docker-library/rabbitmq/issues/357#issuecomment-517755647 404 | cat "$RABBITMQ_SSL_KEYFILE" 405 | } > "$combinedSsl" 406 | chmod 0400 "$combinedSsl" 407 | fi 408 | if [ "$haveSslConfig" ] && [ -f "$combinedSsl" ]; then 409 | # More ENV vars for make clustering happiness 410 | # we don't handle clustering in this script, but these args should ensure 411 | # clustered SSL-enabled members will talk nicely 412 | export ERL_SSL_PATH="$(erl -eval 'io:format("~p", [code:lib_dir(ssl, ebin)]),halt().' -noshell)" 413 | sslErlArgs="-pa $ERL_SSL_PATH -proto_dist inet_tls -ssl_dist_opt server_certfile $combinedSsl -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true" 414 | export RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="${RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS:-} $sslErlArgs" 415 | export RABBITMQ_CTL_ERL_ARGS="${RABBITMQ_CTL_ERL_ARGS:-} $sslErlArgs" 416 | fi 417 | 418 | exec "$@" 419 | -------------------------------------------------------------------------------- /3.8/alpine/management/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM rabbitmq:3.8-alpine 8 | 9 | RUN rabbitmq-plugins enable --offline rabbitmq_management 10 | 11 | # make sure the metrics collector is re-enabled (disabled in the base image for Prometheus-style metrics by default) 12 | RUN rm -f /etc/rabbitmq/conf.d/management_agent.disable_metrics_collector.conf 13 | 14 | # extract "rabbitmqadmin" from inside the "rabbitmq_management-X.Y.Z.ez" plugin zipfile 15 | # see https://github.com/docker-library/rabbitmq/issues/207 16 | RUN set -eux; \ 17 | erl -noinput -eval ' \ 18 | { ok, AdminBin } = zip:foldl(fun(FileInArchive, GetInfo, GetBin, Acc) -> \ 19 | case Acc of \ 20 | "" -> \ 21 | case lists:suffix("/rabbitmqadmin", FileInArchive) of \ 22 | true -> GetBin(); \ 23 | false -> Acc \ 24 | end; \ 25 | _ -> Acc \ 26 | end \ 27 | end, "", init:get_plain_arguments()), \ 28 | io:format("~s", [ AdminBin ]), \ 29 | init:stop(). \ 30 | ' -- /plugins/rabbitmq_management-*.ez > /usr/local/bin/rabbitmqadmin; \ 31 | [ -s /usr/local/bin/rabbitmqadmin ]; \ 32 | chmod +x /usr/local/bin/rabbitmqadmin; \ 33 | apk add --no-cache python3; \ 34 | rabbitmqadmin --version 35 | 36 | EXPOSE 15671 15672 37 | -------------------------------------------------------------------------------- /3.8/ubuntu/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | # The official Canonical Ubuntu Bionic image is ideal from a security perspective, 8 | # especially for the enterprises that we, the RabbitMQ team, have to deal with 9 | FROM ubuntu:18.04 10 | 11 | RUN set -eux; \ 12 | apt-get update; \ 13 | apt-get install -y --no-install-recommends \ 14 | # grab gosu for easy step-down from root 15 | gosu \ 16 | ; \ 17 | rm -rf /var/lib/apt/lists/*; \ 18 | # verify that the "gosu" binary works 19 | gosu nobody true 20 | 21 | # Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally 22 | ARG PGP_KEYSERVER=ha.pool.sks-keyservers.net 23 | # If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, 24 | # run the build with a different PGP_KEYSERVER, e.g. docker build --tag rabbitmq:3.8 --build-arg PGP_KEYSERVER=pgpkeys.eu 3.8/ubuntu 25 | # For context, see https://github.com/docker-library/official-images/issues/4252 26 | 27 | ENV OPENSSL_VERSION 1.1.1j 28 | ENV OPENSSL_SOURCE_SHA256="aaf2fcb575cdf6491b98ab4829abf78a3dec8402b8b81efc8f23c00d443981bf" 29 | # https://www.openssl.org/community/omc.html 30 | ENV OPENSSL_PGP_KEY_IDS="0x8657ABB260F056B1E5190839D9C4D26D0E604491 0x5B2545DAB21995F4088CEFAA36CEE4DEB00CFE33 0xED230BEC4D4F2518B9D7DF41F0DB4D21C1D35231 0xC1F33DD8CE1D4CC613AF14DA9195C48241FBF7DD 0x7953AC1FBC3DC8B3B292393ED5E9E43F7DF9EE8C 0xE5E52560DD91C556DDBDA5D02064C53641C25E5D" 31 | 32 | ENV OTP_VERSION 23.2.5 33 | # TODO add PGP checking when the feature will be added to Erlang/OTP's build system 34 | # https://erlang.org/pipermail/erlang-questions/2019-January/097067.html 35 | ENV OTP_SOURCE_SHA256="0b1ca7d60f4f5a70b56cd0bef77cec2087a53a9a1812d5276a8cd4ce1acfa962" 36 | 37 | # Install dependencies required to build Erlang/OTP from source 38 | # https://erlang.org/doc/installation_guide/INSTALL.html 39 | # autoconf: Required to configure Erlang/OTP before compiling 40 | # dpkg-dev: Required to set up host & build type when compiling Erlang/OTP 41 | # gnupg: Required to verify OpenSSL artefacts 42 | # libncurses5-dev: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli 43 | RUN set -eux; \ 44 | \ 45 | savedAptMark="$(apt-mark showmanual)"; \ 46 | apt-get update; \ 47 | apt-get install --yes --no-install-recommends \ 48 | autoconf \ 49 | ca-certificates \ 50 | dpkg-dev \ 51 | gcc \ 52 | gnupg \ 53 | libncurses5-dev \ 54 | make \ 55 | wget \ 56 | ; \ 57 | rm -rf /var/lib/apt/lists/*; \ 58 | \ 59 | OPENSSL_SOURCE_URL="https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz"; \ 60 | OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ 61 | OPENSSL_CONFIG_DIR=/usr/local/etc/ssl; \ 62 | \ 63 | # Required by the crypto & ssl Erlang/OTP applications 64 | wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_SOURCE_URL.asc"; \ 65 | wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz" "$OPENSSL_SOURCE_URL"; \ 66 | export GNUPGHOME="$(mktemp -d)"; \ 67 | for key in $OPENSSL_PGP_KEY_IDS; do \ 68 | gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \ 69 | done; \ 70 | gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \ 71 | gpgconf --kill all; \ 72 | rm -rf "$GNUPGHOME"; \ 73 | echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum --check --strict -; \ 74 | mkdir -p "$OPENSSL_PATH"; \ 75 | tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \ 76 | \ 77 | # Configure OpenSSL for compilation 78 | cd "$OPENSSL_PATH"; \ 79 | # without specifying "--libdir", Erlang will fail during "crypto:supports()" looking for a "pthread_atfork" function that doesn't exist (but only on arm32v7/armhf??) 80 | debMultiarch="$(dpkg-architecture --query DEB_HOST_MULTIARCH)"; \ 81 | # OpenSSL's "config" script uses a lot of "uname"-based target detection... 82 | MACHINE="$(dpkg-architecture --query DEB_BUILD_GNU_CPU)" \ 83 | RELEASE="4.x.y-z" \ 84 | SYSTEM='Linux' \ 85 | BUILD='???' \ 86 | ./config \ 87 | --openssldir="$OPENSSL_CONFIG_DIR" \ 88 | --libdir="lib/$debMultiarch" \ 89 | # 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) 90 | -Wl,-rpath=/usr/local/lib \ 91 | ; \ 92 | # Compile, install OpenSSL, verify that the command-line works & development headers are present 93 | make -j "$(getconf _NPROCESSORS_ONLN)"; \ 94 | make install_sw install_ssldirs; \ 95 | cd ..; \ 96 | rm -rf "$OPENSSL_PATH"*; \ 97 | ldconfig; \ 98 | # use Debian's CA certificates 99 | rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ 100 | ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR"; \ 101 | # smoke test 102 | openssl version; \ 103 | \ 104 | OTP_SOURCE_URL="https://github.com/erlang/otp/releases/download/OTP-$OTP_VERSION/otp_src_$OTP_VERSION.tar.gz"; \ 105 | OTP_PATH="/usr/local/src/otp-$OTP_VERSION"; \ 106 | \ 107 | # Download, verify & extract OTP_SOURCE 108 | mkdir -p "$OTP_PATH"; \ 109 | wget --progress dot:giga --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \ 110 | echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum --check --strict -; \ 111 | tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \ 112 | \ 113 | # Configure Erlang/OTP for compilation, disable unused features & applications 114 | # https://erlang.org/doc/applications.html 115 | # ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation 116 | cd "$OTP_PATH"; \ 117 | export ERL_TOP="$OTP_PATH"; \ 118 | ./otp_build autoconf; \ 119 | CFLAGS="$(dpkg-buildflags --get CFLAGS)"; export CFLAGS; \ 120 | # 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) 121 | export CFLAGS="$CFLAGS -Wl,-rpath=/usr/local/lib"; \ 122 | hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ 123 | buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ 124 | dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ 125 | ./configure \ 126 | --host="$hostArch" \ 127 | --build="$buildArch" \ 128 | --disable-dynamic-ssl-lib \ 129 | --disable-hipe \ 130 | --disable-sctp \ 131 | --disable-silent-rules \ 132 | --enable-clock-gettime \ 133 | --enable-hybrid-heap \ 134 | --enable-kernel-poll \ 135 | --enable-shared-zlib \ 136 | --enable-smp-support \ 137 | --enable-threads \ 138 | --with-microstate-accounting=extra \ 139 | --without-common_test \ 140 | --without-debugger \ 141 | --without-dialyzer \ 142 | --without-diameter \ 143 | --without-edoc \ 144 | --without-erl_docgen \ 145 | --without-erl_interface \ 146 | --without-et \ 147 | --without-eunit \ 148 | --without-ftp \ 149 | --without-hipe \ 150 | --without-jinterface \ 151 | --without-megaco \ 152 | --without-observer \ 153 | --without-odbc \ 154 | --without-reltool \ 155 | --without-ssh \ 156 | --without-tftp \ 157 | --without-wx \ 158 | ; \ 159 | # Compile & install Erlang/OTP 160 | make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ 161 | make install; \ 162 | cd ..; \ 163 | rm -rf \ 164 | "$OTP_PATH"* \ 165 | /usr/local/lib/erlang/lib/*/examples \ 166 | /usr/local/lib/erlang/lib/*/src \ 167 | ; \ 168 | \ 169 | # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies 170 | apt-mark auto '.*' > /dev/null; \ 171 | [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \ 172 | find /usr/local -type f -executable -exec ldd '{}' ';' \ 173 | | awk '/=>/ { print $(NF-1) }' \ 174 | | sort -u \ 175 | | xargs -r dpkg-query --search \ 176 | | cut -d: -f1 \ 177 | | sort -u \ 178 | | xargs -r apt-mark manual \ 179 | ; \ 180 | apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ 181 | \ 182 | # Check that OpenSSL still works after purging build dependencies 183 | openssl version; \ 184 | # Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly 185 | erl -noshell -eval 'io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' 186 | 187 | ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq 188 | # Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM 189 | RUN set -eux; \ 190 | groupadd --gid 999 --system rabbitmq; \ 191 | useradd --uid 999 --system --home-dir "$RABBITMQ_DATA_DIR" --gid rabbitmq rabbitmq; \ 192 | mkdir -p "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 193 | chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 194 | chmod 777 "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 195 | ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie 196 | 197 | # Use the latest stable RabbitMQ release (https://www.rabbitmq.com/download.html) 198 | ENV RABBITMQ_VERSION 3.8.12 199 | # https://www.rabbitmq.com/signatures.html#importing-gpg 200 | ENV RABBITMQ_PGP_KEY_ID="0x0A9AF2115F4687BD29803A206B73A36E6026DFCA" 201 | ENV RABBITMQ_HOME=/opt/rabbitmq 202 | 203 | # Add RabbitMQ to PATH, send all logs to TTY 204 | ENV PATH=$RABBITMQ_HOME/sbin:$PATH \ 205 | RABBITMQ_LOGS=- 206 | 207 | # Install RabbitMQ 208 | RUN set -eux; \ 209 | \ 210 | savedAptMark="$(apt-mark showmanual)"; \ 211 | apt-get update; \ 212 | apt-get install --yes --no-install-recommends \ 213 | ca-certificates \ 214 | gnupg \ 215 | wget \ 216 | xz-utils \ 217 | ; \ 218 | rm -rf /var/lib/apt/lists/*; \ 219 | \ 220 | RABBITMQ_SOURCE_URL="https://github.com/rabbitmq/rabbitmq-server/releases/download/v$RABBITMQ_VERSION/rabbitmq-server-generic-unix-latest-toolchain-$RABBITMQ_VERSION.tar.xz"; \ 221 | RABBITMQ_PATH="/usr/local/src/rabbitmq-$RABBITMQ_VERSION"; \ 222 | \ 223 | wget --progress dot:giga --output-document "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_SOURCE_URL.asc"; \ 224 | wget --progress dot:giga --output-document "$RABBITMQ_PATH.tar.xz" "$RABBITMQ_SOURCE_URL"; \ 225 | \ 226 | export GNUPGHOME="$(mktemp -d)"; \ 227 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$RABBITMQ_PGP_KEY_ID"; \ 228 | gpg --batch --verify "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_PATH.tar.xz"; \ 229 | gpgconf --kill all; \ 230 | rm -rf "$GNUPGHOME"; \ 231 | \ 232 | mkdir -p "$RABBITMQ_HOME"; \ 233 | tar --extract --file "$RABBITMQ_PATH.tar.xz" --directory "$RABBITMQ_HOME" --strip-components 1; \ 234 | rm -rf "$RABBITMQ_PATH"*; \ 235 | # Do not default SYS_PREFIX to RABBITMQ_HOME, leave it empty 236 | grep -qE '^SYS_PREFIX=\$\{RABBITMQ_HOME\}$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 237 | sed -i 's/^SYS_PREFIX=.*$/SYS_PREFIX=/' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 238 | grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 239 | chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ 240 | \ 241 | apt-mark auto '.*' > /dev/null; \ 242 | apt-mark manual $savedAptMark; \ 243 | apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ 244 | \ 245 | # verify assumption of no stale cookies 246 | [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ 247 | # Ensure RabbitMQ was installed correctly by running a few commands that do not depend on a running server, as the rabbitmq user 248 | # If they all succeed, it's safe to assume that things have been set up correctly 249 | gosu rabbitmq rabbitmqctl help; \ 250 | gosu rabbitmq rabbitmqctl list_ciphers; \ 251 | gosu rabbitmq rabbitmq-plugins list; \ 252 | # no stale cookies 253 | rm "$RABBITMQ_DATA_DIR/.erlang.cookie" 254 | 255 | # Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) 256 | RUN set -eux; \ 257 | rabbitmq-plugins enable --offline rabbitmq_prometheus; \ 258 | echo 'management_agent.disable_metrics_collector = true' > /etc/rabbitmq/conf.d/management_agent.disable_metrics_collector.conf 259 | 260 | # Added for backwards compatibility - users can simply COPY custom plugins to /plugins 261 | RUN ln -sf /opt/rabbitmq/plugins /plugins 262 | 263 | # set home so that any `--user` knows where to put the erlang cookie 264 | ENV HOME $RABBITMQ_DATA_DIR 265 | # Hint that the data (a.k.a. home dir) dir should be separate volume 266 | VOLUME $RABBITMQ_DATA_DIR 267 | 268 | # 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) 269 | # 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 270 | # https://docs.docker.com/samples/library/ubuntu/#locales 271 | ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 272 | 273 | COPY docker-entrypoint.sh /usr/local/bin/ 274 | ENTRYPOINT ["docker-entrypoint.sh"] 275 | 276 | EXPOSE 4369 5671 5672 15691 15692 25672 277 | CMD ["rabbitmq-server"] 278 | -------------------------------------------------------------------------------- /3.8/ubuntu/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eu 3 | 4 | # usage: file_env VAR [DEFAULT] 5 | # ie: file_env 'XYZ_DB_PASSWORD' 'example' 6 | # (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of 7 | # "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) 8 | file_env() { 9 | local var="$1" 10 | local fileVar="${var}_FILE" 11 | local def="${2:-}" 12 | if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then 13 | echo >&2 "error: both $var and $fileVar are set (but are exclusive)" 14 | exit 1 15 | fi 16 | local val="$def" 17 | if [ "${!var:-}" ]; then 18 | val="${!var}" 19 | elif [ "${!fileVar:-}" ]; then 20 | val="$(< "${!fileVar}")" 21 | fi 22 | export "$var"="$val" 23 | unset "$fileVar" 24 | } 25 | 26 | # backwards compatibility for old environment variables 27 | : "${RABBITMQ_SSL_CERTFILE:=${RABBITMQ_SSL_CERT_FILE:-}}" 28 | : "${RABBITMQ_SSL_KEYFILE:=${RABBITMQ_SSL_KEY_FILE:-}}" 29 | : "${RABBITMQ_SSL_CACERTFILE:=${RABBITMQ_SSL_CA_FILE:-}}" 30 | 31 | # "management" SSL config should default to using the same certs 32 | : "${RABBITMQ_MANAGEMENT_SSL_CACERTFILE:=$RABBITMQ_SSL_CACERTFILE}" 33 | : "${RABBITMQ_MANAGEMENT_SSL_CERTFILE:=$RABBITMQ_SSL_CERTFILE}" 34 | : "${RABBITMQ_MANAGEMENT_SSL_KEYFILE:=$RABBITMQ_SSL_KEYFILE}" 35 | 36 | # Allowed env vars that will be read from mounted files (i.e. Docker Secrets): 37 | fileEnvKeys=( 38 | default_user 39 | default_pass 40 | ) 41 | 42 | # https://www.rabbitmq.com/configure.html 43 | sslConfigKeys=( 44 | cacertfile 45 | certfile 46 | depth 47 | fail_if_no_peer_cert 48 | keyfile 49 | verify 50 | ) 51 | managementConfigKeys=( 52 | "${sslConfigKeys[@]/#/ssl_}" 53 | ) 54 | rabbitConfigKeys=( 55 | default_pass 56 | default_user 57 | default_vhost 58 | vm_memory_high_watermark 59 | ) 60 | fileConfigKeys=( 61 | management_ssl_cacertfile 62 | management_ssl_certfile 63 | management_ssl_keyfile 64 | ssl_cacertfile 65 | ssl_certfile 66 | ssl_keyfile 67 | ) 68 | allConfigKeys=( 69 | "${managementConfigKeys[@]/#/management_}" 70 | "${rabbitConfigKeys[@]}" 71 | "${sslConfigKeys[@]/#/ssl_}" 72 | ) 73 | 74 | declare -A configDefaults=( 75 | [management_ssl_fail_if_no_peer_cert]='false' 76 | [management_ssl_verify]='verify_none' 77 | 78 | [ssl_fail_if_no_peer_cert]='true' 79 | [ssl_verify]='verify_peer' 80 | ) 81 | 82 | # allow the container to be started with `--user` 83 | if [[ "$1" == rabbitmq* ]] && [ "$(id -u)" = '0' ]; then 84 | # this needs to happen late enough that we have the SSL config 85 | # https://github.com/docker-library/rabbitmq/issues/283 86 | for conf in "${allConfigKeys[@]}"; do 87 | var="RABBITMQ_${conf^^}" 88 | val="${!var:-}" 89 | [ -n "$val" ] || continue 90 | case "$conf" in 91 | *_ssl_*file | ssl_*file ) 92 | if [ -f "$val" ] && ! gosu rabbitmq test -r "$val"; then 93 | newFile="/tmp/rabbitmq-ssl/$conf.pem" 94 | echo >&2 95 | echo >&2 "WARNING: '$val' ($var) is not readable by rabbitmq ($(id rabbitmq)); copying to '$newFile'" 96 | echo >&2 97 | cat "$val" > "$newFile" 98 | chown rabbitmq "$newFile" 99 | chmod 0400 "$newFile" 100 | eval 'export '$var'="$newFile"' 101 | fi 102 | ;; 103 | esac 104 | done 105 | 106 | if [ "$1" = 'rabbitmq-server' ]; then 107 | find /var/lib/rabbitmq \! -user rabbitmq -exec chown rabbitmq '{}' + 108 | fi 109 | 110 | exec gosu rabbitmq "$BASH_SOURCE" "$@" 111 | fi 112 | 113 | haveConfig= 114 | haveSslConfig= 115 | haveManagementSslConfig= 116 | for fileEnvKey in "${fileEnvKeys[@]}"; do file_env "RABBITMQ_${fileEnvKey^^}"; done 117 | for conf in "${allConfigKeys[@]}"; do 118 | var="RABBITMQ_${conf^^}" 119 | val="${!var:-}" 120 | if [ "$val" ]; then 121 | if [ "${configDefaults[$conf]:-}" ] && [ "${configDefaults[$conf]}" = "$val" ]; then 122 | # if the value set is the same as the default, treat it as if it isn't set 123 | continue 124 | fi 125 | haveConfig=1 126 | case "$conf" in 127 | ssl_*) haveSslConfig=1 ;; 128 | management_ssl_*) haveManagementSslConfig=1 ;; 129 | esac 130 | fi 131 | done 132 | if [ "$haveSslConfig" ]; then 133 | missing=() 134 | for sslConf in cacertfile certfile keyfile; do 135 | var="RABBITMQ_SSL_${sslConf^^}" 136 | val="${!var}" 137 | if [ -z "$val" ]; then 138 | missing+=( "$var" ) 139 | fi 140 | done 141 | if [ "${#missing[@]}" -gt 0 ]; then 142 | { 143 | echo 144 | echo 'error: SSL requested, but missing required configuration' 145 | for miss in "${missing[@]}"; do 146 | echo " - $miss" 147 | done 148 | echo 149 | } >&2 150 | exit 1 151 | fi 152 | fi 153 | missingFiles=() 154 | for conf in "${fileConfigKeys[@]}"; do 155 | var="RABBITMQ_${conf^^}" 156 | val="${!var}" 157 | if [ "$val" ] && [ ! -f "$val" ]; then 158 | missingFiles+=( "$val ($var)" ) 159 | fi 160 | done 161 | if [ "${#missingFiles[@]}" -gt 0 ]; then 162 | { 163 | echo 164 | echo 'error: files specified, but missing' 165 | for miss in "${missingFiles[@]}"; do 166 | echo " - $miss" 167 | done 168 | echo 169 | } >&2 170 | exit 1 171 | fi 172 | 173 | # set defaults for missing values (but only after we're done with all our checking so we don't throw any of that off) 174 | for conf in "${!configDefaults[@]}"; do 175 | default="${configDefaults[$conf]}" 176 | var="RABBITMQ_${conf^^}" 177 | [ -z "${!var:-}" ] || continue 178 | eval "export $var=\"\$default\"" 179 | done 180 | 181 | # if long and short hostnames are not the same, use long hostnames 182 | if [ "$(hostname)" != "$(hostname -s)" ]; then 183 | : "${RABBITMQ_USE_LONGNAME:=true}" 184 | fi 185 | 186 | if [ "${RABBITMQ_ERLANG_COOKIE:-}" ]; then 187 | cookieFile='/var/lib/rabbitmq/.erlang.cookie' 188 | if [ -e "$cookieFile" ]; then 189 | if [ "$(cat "$cookieFile" 2>/dev/null)" != "$RABBITMQ_ERLANG_COOKIE" ]; then 190 | echo >&2 191 | echo >&2 "warning: $cookieFile contents do not match RABBITMQ_ERLANG_COOKIE" 192 | echo >&2 193 | fi 194 | else 195 | echo "$RABBITMQ_ERLANG_COOKIE" > "$cookieFile" 196 | fi 197 | chmod 600 "$cookieFile" 198 | fi 199 | 200 | configBase="${RABBITMQ_CONFIG_FILE:-/etc/rabbitmq/rabbitmq}" 201 | oldConfigFile="$configBase.config" 202 | newConfigFile="$configBase.conf" 203 | 204 | shouldWriteConfig="$haveConfig" 205 | if [ -n "$shouldWriteConfig" ] && ! touch "$newConfigFile"; then 206 | # config file exists but it isn't writeable (likely read-only mount, such as Kubernetes configMap) 207 | export RABBITMQ_CONFIG_FILE='/tmp/rabbitmq.conf' 208 | cp "$newConfigFile" "$RABBITMQ_CONFIG_FILE" 209 | echo >&2 210 | echo >&2 "WARNING: '$newConfigFile' is not writable, but environment variables have been provided which request that we write to it" 211 | echo >&2 " We have copied it to '$RABBITMQ_CONFIG_FILE' so it can be amended to work around the problem, but it is recommended that the read-only source file should be modified and the environment variables removed instead." 212 | echo >&2 213 | newConfigFile="$RABBITMQ_CONFIG_FILE" 214 | fi 215 | if [ -n "$shouldWriteConfig" ] && [ -f "$oldConfigFile" ]; then 216 | { 217 | echo "error: Docker configuration environment variables specified, but old-style (Erlang syntax) configuration file '$oldConfigFile' exists" 218 | echo " Suggested fixes: (choose one)" 219 | echo " - remove '$oldConfigFile'" 220 | echo " - remove any Docker-specific 'RABBITMQ_...' environment variables" 221 | echo " - convert '$oldConfigFile' to the newer sysctl format ('$newConfigFile'); see https://www.rabbitmq.com/configure.html#config-file" 222 | } >&2 223 | exit 1 224 | fi 225 | if [ -z "$shouldWriteConfig" ] && [ ! -f "$oldConfigFile" ] && [ ! -f "$newConfigFile" ]; then 226 | # no config files, we should write one 227 | shouldWriteConfig=1 228 | fi 229 | 230 | # http://stackoverflow.com/a/2705678/433558 231 | sed_escape_lhs() { 232 | echo "$@" | sed -e 's/[]\/$*.^|[]/\\&/g' 233 | } 234 | sed_escape_rhs() { 235 | echo "$@" | sed -e 's/[\/&]/\\&/g' 236 | } 237 | rabbit_set_config() { 238 | local key="$1"; shift 239 | local val="$1"; shift 240 | 241 | [ -e "$newConfigFile" ] || touch "$newConfigFile" 242 | 243 | local sedKey="$(sed_escape_lhs "$key")" 244 | local sedVal="$(sed_escape_rhs "$val")" 245 | sed -ri \ 246 | "s/^[[:space:]]*(${sedKey}[[:space:]]*=[[:space:]]*)\S.*\$/\1${sedVal}/" \ 247 | "$newConfigFile" 248 | if ! grep -qE "^${sedKey}[[:space:]]*=" "$newConfigFile"; then 249 | sed -i -e '$a\' "$newConfigFile" # https://github.com/docker-library/rabbitmq/issues/456#issuecomment-752251872 (https://unix.stackexchange.com/a/31955/153467) 250 | echo "$key = $val" >> "$newConfigFile" 251 | fi 252 | } 253 | rabbit_comment_config() { 254 | local key="$1"; shift 255 | 256 | [ -e "$newConfigFile" ] || touch "$newConfigFile" 257 | 258 | local sedKey="$(sed_escape_lhs "$key")" 259 | sed -ri \ 260 | "s/^[[:space:]]*#?[[:space:]]*(${sedKey}[[:space:]]*=[[:space:]]*\S.*)\$/# \1/" \ 261 | "$newConfigFile" 262 | } 263 | rabbit_env_config() { 264 | local prefix="$1"; shift 265 | 266 | local conf 267 | for conf; do 268 | local var="rabbitmq${prefix:+_$prefix}_$conf" 269 | var="${var^^}" 270 | 271 | local key="$conf" 272 | case "$prefix" in 273 | ssl) key="ssl_options.$key" ;; 274 | management_ssl) key="management.ssl.$key" ;; 275 | esac 276 | 277 | local val="${!var:-}" 278 | local rawVal="$val" 279 | case "$conf" in 280 | fail_if_no_peer_cert) 281 | case "${val,,}" in 282 | false|no|0|'') rawVal='false' ;; 283 | true|yes|1|*) rawVal='true' ;; 284 | esac 285 | ;; 286 | 287 | vm_memory_high_watermark) continue ;; # handled separately 288 | esac 289 | 290 | if [ -n "$rawVal" ]; then 291 | rabbit_set_config "$key" "$rawVal" 292 | else 293 | rabbit_comment_config "$key" 294 | fi 295 | done 296 | } 297 | 298 | if [ "$1" = 'rabbitmq-server' ] && [ "$shouldWriteConfig" ]; then 299 | rabbit_set_config 'loopback_users.guest' 'false' 300 | 301 | # determine whether to set "vm_memory_high_watermark" (based on cgroups) 302 | memTotalKb= 303 | if [ -r /proc/meminfo ]; then 304 | memTotalKb="$(awk -F ':? +' '$1 == "MemTotal" { print $2; exit }' /proc/meminfo)" 305 | fi 306 | memLimitB= 307 | if [ -r /sys/fs/cgroup/memory/memory.limit_in_bytes ]; then 308 | # "18446744073709551615" is a valid value for "memory.limit_in_bytes", which is too big for Bash math to handle 309 | # "$(( 18446744073709551615 / 1024 ))" = 0; "$(( 18446744073709551615 * 40 / 100 ))" = 0 310 | memLimitB="$(awk -v totKb="$memTotalKb" '{ 311 | limB = $0; 312 | limKb = limB / 1024; 313 | if (!totKb || limKb < totKb) { 314 | printf "%.0f\n", limB; 315 | } 316 | }' /sys/fs/cgroup/memory/memory.limit_in_bytes)" 317 | fi 318 | if [ -n "$memLimitB" ]; then 319 | # if we have a cgroup memory limit, let's inform RabbitMQ of what it is (so it can calculate vm_memory_high_watermark properly) 320 | # https://github.com/rabbitmq/rabbitmq-server/pull/1234 321 | rabbit_set_config 'total_memory_available_override_value' "$memLimitB" 322 | fi 323 | # https://www.rabbitmq.com/memory.html#memsup-usage 324 | if [ "${RABBITMQ_VM_MEMORY_HIGH_WATERMARK:-}" ]; then 325 | # https://github.com/docker-library/rabbitmq/pull/105#issuecomment-242165822 326 | vmMemoryHighWatermark="$( 327 | echo "$RABBITMQ_VM_MEMORY_HIGH_WATERMARK" | awk ' 328 | /^[0-9]*[.][0-9]+$|^[0-9]+([.][0-9]+)?%$/ { 329 | perc = $0; 330 | if (perc ~ /%$/) { 331 | gsub(/%$/, "", perc); 332 | perc = perc / 100; 333 | } 334 | if (perc > 1.0 || perc < 0.0) { 335 | printf "error: invalid percentage for vm_memory_high_watermark: %s (must be >= 0%%, <= 100%%)\n", $0 > "/dev/stderr"; 336 | exit 1; 337 | } 338 | printf "vm_memory_high_watermark.relative %0.03f\n", perc; 339 | next; 340 | } 341 | /^[0-9]+$/ { 342 | printf "vm_memory_high_watermark.absolute %s\n", $0; 343 | next; 344 | } 345 | /^[0-9]+([.][0-9]+)?[a-zA-Z]+$/ { 346 | printf "vm_memory_high_watermark.absolute %s\n", $0; 347 | next; 348 | } 349 | { 350 | printf "error: unexpected input for vm_memory_high_watermark: %s\n", $0; 351 | exit 1; 352 | } 353 | ' 354 | )" 355 | if [ "$vmMemoryHighWatermark" ]; then 356 | vmMemoryHighWatermarkKey="${vmMemoryHighWatermark%% *}" 357 | vmMemoryHighWatermarkVal="${vmMemoryHighWatermark#$vmMemoryHighWatermarkKey }" 358 | rabbit_set_config "$vmMemoryHighWatermarkKey" "$vmMemoryHighWatermarkVal" 359 | case "$vmMemoryHighWatermarkKey" in 360 | # make sure we only set one or the other 361 | 'vm_memory_high_watermark.absolute') rabbit_comment_config 'vm_memory_high_watermark.relative' ;; 362 | 'vm_memory_high_watermark.relative') rabbit_comment_config 'vm_memory_high_watermark.absolute' ;; 363 | esac 364 | fi 365 | fi 366 | 367 | if [ "$haveSslConfig" ]; then 368 | rabbit_set_config 'listeners.ssl.default' 5671 369 | rabbit_env_config 'ssl' "${sslConfigKeys[@]}" 370 | else 371 | rabbit_set_config 'listeners.tcp.default' 5672 372 | fi 373 | 374 | rabbit_env_config '' "${rabbitConfigKeys[@]}" 375 | 376 | # if management plugin is installed, generate config for it 377 | # https://www.rabbitmq.com/management.html#configuration 378 | if [ "$(rabbitmq-plugins list -q -m -e rabbitmq_management)" ]; then 379 | if [ "$haveManagementSslConfig" ]; then 380 | rabbit_set_config 'management.ssl.port' 15671 381 | rabbit_env_config 'management_ssl' "${sslConfigKeys[@]}" 382 | else 383 | rabbit_set_config 'management.tcp.port' 15672 384 | fi 385 | 386 | # if definitions file exists, then load it 387 | # https://www.rabbitmq.com/management.html#load-definitions 388 | managementDefinitionsFile='/etc/rabbitmq/definitions.json' 389 | if [ -f "$managementDefinitionsFile" ]; then 390 | # We use `load_definitions` (the built-in setting as of 3.8.2+) instead 391 | # of `management.load_definitions`. 392 | # See https://github.com/docker-library/rabbitmq/issues/429 for details. 393 | rabbit_set_config 'load_definitions' "$managementDefinitionsFile" 394 | fi 395 | fi 396 | fi 397 | 398 | combinedSsl='/tmp/rabbitmq-ssl/combined.pem' 399 | if [ "$haveSslConfig" ] && [[ "$1" == rabbitmq* ]] && [ ! -f "$combinedSsl" ]; then 400 | # Create combined cert 401 | { 402 | cat "$RABBITMQ_SSL_CERTFILE" 403 | echo # https://github.com/docker-library/rabbitmq/issues/357#issuecomment-517755647 404 | cat "$RABBITMQ_SSL_KEYFILE" 405 | } > "$combinedSsl" 406 | chmod 0400 "$combinedSsl" 407 | fi 408 | if [ "$haveSslConfig" ] && [ -f "$combinedSsl" ]; then 409 | # More ENV vars for make clustering happiness 410 | # we don't handle clustering in this script, but these args should ensure 411 | # clustered SSL-enabled members will talk nicely 412 | export ERL_SSL_PATH="$(erl -eval 'io:format("~p", [code:lib_dir(ssl, ebin)]),halt().' -noshell)" 413 | sslErlArgs="-pa $ERL_SSL_PATH -proto_dist inet_tls -ssl_dist_opt server_certfile $combinedSsl -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true" 414 | export RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="${RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS:-} $sslErlArgs" 415 | export RABBITMQ_CTL_ERL_ARGS="${RABBITMQ_CTL_ERL_ARGS:-} $sslErlArgs" 416 | fi 417 | 418 | exec "$@" 419 | -------------------------------------------------------------------------------- /3.8/ubuntu/management/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM rabbitmq:3.8 8 | 9 | RUN rabbitmq-plugins enable --offline rabbitmq_management 10 | 11 | # make sure the metrics collector is re-enabled (disabled in the base image for Prometheus-style metrics by default) 12 | RUN rm -f /etc/rabbitmq/conf.d/management_agent.disable_metrics_collector.conf 13 | 14 | # extract "rabbitmqadmin" from inside the "rabbitmq_management-X.Y.Z.ez" plugin zipfile 15 | # see https://github.com/docker-library/rabbitmq/issues/207 16 | RUN set -eux; \ 17 | erl -noinput -eval ' \ 18 | { ok, AdminBin } = zip:foldl(fun(FileInArchive, GetInfo, GetBin, Acc) -> \ 19 | case Acc of \ 20 | "" -> \ 21 | case lists:suffix("/rabbitmqadmin", FileInArchive) of \ 22 | true -> GetBin(); \ 23 | false -> Acc \ 24 | end; \ 25 | _ -> Acc \ 26 | end \ 27 | end, "", init:get_plain_arguments()), \ 28 | io:format("~s", [ AdminBin ]), \ 29 | init:stop(). \ 30 | ' -- /plugins/rabbitmq_management-*.ez > /usr/local/bin/rabbitmqadmin; \ 31 | [ -s /usr/local/bin/rabbitmqadmin ]; \ 32 | chmod +x /usr/local/bin/rabbitmqadmin; \ 33 | apt-get update; \ 34 | apt-get install -y --no-install-recommends python3; \ 35 | rm -rf /var/lib/apt/lists/*; \ 36 | rabbitmqadmin --version 37 | 38 | EXPOSE 15671 15672 39 | -------------------------------------------------------------------------------- /Dockerfile-alpine.template: -------------------------------------------------------------------------------- 1 | # Alpine Linux is not officially supported by the RabbitMQ team -- use at your own risk! 2 | FROM alpine:3.13 3 | 4 | RUN apk add --no-cache \ 5 | # grab su-exec for easy step-down from root 6 | 'su-exec>=0.2' \ 7 | # bash for docker-entrypoint.sh 8 | bash \ 9 | # "ps" for "rabbitmqctl wait" (https://github.com/docker-library/rabbitmq/issues/162) 10 | procps 11 | 12 | # Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally 13 | ARG PGP_KEYSERVER=ha.pool.sks-keyservers.net 14 | # If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, 15 | # run the build with a different PGP_KEYSERVER, e.g. docker build --tag rabbitmq:3.8 --build-arg PGP_KEYSERVER=pgpkeys.eu 3.8/ubuntu 16 | # For context, see https://github.com/docker-library/official-images/issues/4252 17 | 18 | ENV OPENSSL_VERSION {{ .openssl.version }} 19 | ENV OPENSSL_SOURCE_SHA256="{{ .openssl.sha256 }}" 20 | # https://www.openssl.org/community/omc.html 21 | ENV OPENSSL_PGP_KEY_IDS="{{ 22 | [ 23 | # Matt Caswell 24 | "8657 ABB2 60F0 56B1 E519 0839 D9C4 D26D 0E60 4491", 25 | 26 | # Mark J. Cox 27 | "5B25 45DA B219 95F4 088C EFAA 36CE E4DE B00C FE33", 28 | 29 | # Paul Dale 30 | "ED23 0BEC 4D4F 2518 B9D7 DF41 F0DB 4D21 C1D3 5231", 31 | 32 | # Tim Hudson 33 | "C1F3 3DD8 CE1D 4CC6 13AF 14DA 9195 C482 41FB F7DD", 34 | 35 | # Richard Levitte 36 | "7953 AC1F BC3D C8B3 B292 393E D5E9 E43F 7DF9 EE8C", 37 | 38 | # Kurt Roeckx 39 | "E5E5 2560 DD91 C556 DDBD A5D0 2064 C536 41C2 5E5D" 40 | ] 41 | # 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?) 42 | | map("0x" + gsub(" "; "")) | join(" ") 43 | }}" 44 | 45 | ENV OTP_VERSION {{ .otp.version }} 46 | # TODO add PGP checking when the feature will be added to Erlang/OTP's build system 47 | # https://erlang.org/pipermail/erlang-questions/2019-January/097067.html 48 | ENV OTP_SOURCE_SHA256="{{ .otp.sha256 }}" 49 | 50 | # Install dependencies required to build Erlang/OTP from source 51 | # https://erlang.org/doc/installation_guide/INSTALL.html 52 | # autoconf: Required to configure Erlang/OTP before compiling 53 | # dpkg-dev: Required to set up host & build type when compiling Erlang/OTP 54 | # gnupg: Required to verify OpenSSL artefacts 55 | # libncurses5-dev: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli 56 | RUN set -eux; \ 57 | \ 58 | apk add --no-cache --virtual .build-deps \ 59 | autoconf \ 60 | dpkg-dev dpkg \ 61 | gcc \ 62 | gnupg \ 63 | libc-dev \ 64 | linux-headers \ 65 | make \ 66 | ncurses-dev \ 67 | ; \ 68 | \ 69 | OPENSSL_SOURCE_URL="https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz"; \ 70 | OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ 71 | OPENSSL_CONFIG_DIR=/usr/local/etc/ssl; \ 72 | \ 73 | # /usr/local/src doesn't exist in Alpine by default 74 | mkdir /usr/local/src; \ 75 | \ 76 | # Required by the crypto & ssl Erlang/OTP applications 77 | wget --output-document "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_SOURCE_URL.asc"; \ 78 | wget --output-document "$OPENSSL_PATH.tar.gz" "$OPENSSL_SOURCE_URL"; \ 79 | export GNUPGHOME="$(mktemp -d)"; \ 80 | for key in $OPENSSL_PGP_KEY_IDS; do \ 81 | gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \ 82 | done; \ 83 | gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \ 84 | gpgconf --kill all; \ 85 | rm -rf "$GNUPGHOME"; \ 86 | echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum -c -; \ 87 | mkdir -p "$OPENSSL_PATH"; \ 88 | tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \ 89 | \ 90 | # Configure OpenSSL for compilation 91 | cd "$OPENSSL_PATH"; \ 92 | # OpenSSL's "config" script uses a lot of "uname"-based target detection... 93 | MACHINE="$(dpkg-architecture --query DEB_BUILD_GNU_CPU)" \ 94 | RELEASE="4.x.y-z" \ 95 | SYSTEM='Linux' \ 96 | BUILD='???' \ 97 | ./config \ 98 | --openssldir="$OPENSSL_CONFIG_DIR" \ 99 | # 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) 100 | -Wl,-rpath=/usr/local/lib \ 101 | ; \ 102 | # Compile, install OpenSSL, verify that the command-line works & development headers are present 103 | make -j "$(getconf _NPROCESSORS_ONLN)"; \ 104 | make install_sw install_ssldirs; \ 105 | cd ..; \ 106 | rm -rf "$OPENSSL_PATH"*; \ 107 | # use Alpine's CA certificates 108 | rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ 109 | ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR"; \ 110 | # smoke test 111 | openssl version; \ 112 | \ 113 | OTP_SOURCE_URL="https://github.com/erlang/otp/releases/download/OTP-$OTP_VERSION/otp_src_$OTP_VERSION.tar.gz"; \ 114 | OTP_PATH="/usr/local/src/otp-$OTP_VERSION"; \ 115 | \ 116 | # Download, verify & extract OTP_SOURCE 117 | mkdir -p "$OTP_PATH"; \ 118 | wget --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \ 119 | echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum -c -; \ 120 | tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \ 121 | \ 122 | # Configure Erlang/OTP for compilation, disable unused features & applications 123 | # https://erlang.org/doc/applications.html 124 | # ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation 125 | cd "$OTP_PATH"; \ 126 | export ERL_TOP="$OTP_PATH"; \ 127 | ./otp_build autoconf; \ 128 | export CFLAGS='-g -O2'; \ 129 | # 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) 130 | export CFLAGS="$CFLAGS -Wl,-rpath=/usr/local/lib"; \ 131 | hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ 132 | buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ 133 | dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ 134 | ./configure \ 135 | --host="$hostArch" \ 136 | --build="$buildArch" \ 137 | --disable-dynamic-ssl-lib \ 138 | --disable-hipe \ 139 | --disable-sctp \ 140 | --disable-silent-rules \ 141 | --enable-clock-gettime \ 142 | --enable-hybrid-heap \ 143 | --enable-kernel-poll \ 144 | --enable-shared-zlib \ 145 | --enable-smp-support \ 146 | --enable-threads \ 147 | --with-microstate-accounting=extra \ 148 | --without-common_test \ 149 | --without-debugger \ 150 | --without-dialyzer \ 151 | --without-diameter \ 152 | --without-edoc \ 153 | --without-erl_docgen \ 154 | --without-erl_interface \ 155 | --without-et \ 156 | --without-eunit \ 157 | --without-ftp \ 158 | --without-hipe \ 159 | --without-jinterface \ 160 | --without-megaco \ 161 | --without-observer \ 162 | --without-odbc \ 163 | --without-reltool \ 164 | --without-ssh \ 165 | --without-tftp \ 166 | --without-wx \ 167 | ; \ 168 | # Compile & install Erlang/OTP 169 | make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ 170 | make install; \ 171 | cd ..; \ 172 | rm -rf \ 173 | "$OTP_PATH"* \ 174 | /usr/local/lib/erlang/lib/*/examples \ 175 | /usr/local/lib/erlang/lib/*/src \ 176 | ; \ 177 | \ 178 | runDeps="$( \ 179 | scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ 180 | | tr ',' '\n' \ 181 | | sort -u \ 182 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 183 | )"; \ 184 | apk add --no-cache --virtual .otp-run-deps $runDeps; \ 185 | apk del --no-network .build-deps; \ 186 | \ 187 | # Check that OpenSSL still works after purging build dependencies 188 | openssl version; \ 189 | # Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly 190 | erl -noshell -eval 'io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' 191 | 192 | ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq 193 | # Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM 194 | RUN set -eux; \ 195 | addgroup -g 101 -S rabbitmq; \ 196 | adduser -u 100 -S -h "$RABBITMQ_DATA_DIR" -G rabbitmq rabbitmq; \ 197 | mkdir -p "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 198 | chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 199 | chmod 777 "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 200 | ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie 201 | 202 | # Use the latest stable RabbitMQ release (https://www.rabbitmq.com/download.html) 203 | ENV RABBITMQ_VERSION {{ .version }} 204 | # https://www.rabbitmq.com/signatures.html#importing-gpg 205 | ENV RABBITMQ_PGP_KEY_ID="0x0A9AF2115F4687BD29803A206B73A36E6026DFCA" 206 | ENV RABBITMQ_HOME=/opt/rabbitmq 207 | 208 | # Add RabbitMQ to PATH, send all logs to TTY 209 | ENV PATH=$RABBITMQ_HOME/sbin:$PATH \ 210 | RABBITMQ_LOGS=- 211 | 212 | # Install RabbitMQ 213 | RUN set -eux; \ 214 | \ 215 | apk add --no-cache --virtual .build-deps \ 216 | gnupg \ 217 | xz \ 218 | ; \ 219 | \ 220 | RABBITMQ_SOURCE_URL="https://github.com/rabbitmq/rabbitmq-server/releases/download/v$RABBITMQ_VERSION/rabbitmq-server-generic-unix-latest-toolchain-$RABBITMQ_VERSION.tar.xz"; \ 221 | RABBITMQ_PATH="/usr/local/src/rabbitmq-$RABBITMQ_VERSION"; \ 222 | \ 223 | wget --output-document "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_SOURCE_URL.asc"; \ 224 | wget --output-document "$RABBITMQ_PATH.tar.xz" "$RABBITMQ_SOURCE_URL"; \ 225 | \ 226 | export GNUPGHOME="$(mktemp -d)"; \ 227 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$RABBITMQ_PGP_KEY_ID"; \ 228 | gpg --batch --verify "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_PATH.tar.xz"; \ 229 | gpgconf --kill all; \ 230 | rm -rf "$GNUPGHOME"; \ 231 | \ 232 | mkdir -p "$RABBITMQ_HOME"; \ 233 | tar --extract --file "$RABBITMQ_PATH.tar.xz" --directory "$RABBITMQ_HOME" --strip-components 1; \ 234 | rm -rf "$RABBITMQ_PATH"*; \ 235 | # Do not default SYS_PREFIX to RABBITMQ_HOME, leave it empty 236 | grep -qE '^SYS_PREFIX=\$\{RABBITMQ_HOME\}$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 237 | sed -i 's/^SYS_PREFIX=.*$/SYS_PREFIX=/' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 238 | grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 239 | chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ 240 | \ 241 | apk del .build-deps; \ 242 | \ 243 | # verify assumption of no stale cookies 244 | [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ 245 | # Ensure RabbitMQ was installed correctly by running a few commands that do not depend on a running server, as the rabbitmq user 246 | # If they all succeed, it's safe to assume that things have been set up correctly 247 | su-exec rabbitmq rabbitmqctl help; \ 248 | su-exec rabbitmq rabbitmqctl list_ciphers; \ 249 | su-exec rabbitmq rabbitmq-plugins list; \ 250 | # no stale cookies 251 | rm "$RABBITMQ_DATA_DIR/.erlang.cookie" 252 | 253 | # Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) 254 | RUN set -eux; \ 255 | rabbitmq-plugins enable --offline rabbitmq_prometheus; \ 256 | echo 'management_agent.disable_metrics_collector = true' > /etc/rabbitmq/conf.d/management_agent.disable_metrics_collector.conf 257 | 258 | # Added for backwards compatibility - users can simply COPY custom plugins to /plugins 259 | RUN ln -sf /opt/rabbitmq/plugins /plugins 260 | 261 | # set home so that any `--user` knows where to put the erlang cookie 262 | ENV HOME $RABBITMQ_DATA_DIR 263 | # Hint that the data (a.k.a. home dir) dir should be separate volume 264 | VOLUME $RABBITMQ_DATA_DIR 265 | 266 | # 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) 267 | # 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 268 | # https://docs.docker.com/samples/library/ubuntu/#locales 269 | ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 270 | 271 | COPY docker-entrypoint.sh /usr/local/bin/ 272 | ENTRYPOINT ["docker-entrypoint.sh"] 273 | 274 | EXPOSE 4369 5671 5672 15691 15692 25672 275 | CMD ["rabbitmq-server"] 276 | -------------------------------------------------------------------------------- /Dockerfile-management.template: -------------------------------------------------------------------------------- 1 | FROM {{ 2 | "rabbitmq:" + env.version 3 | + if env.variant == "alpine" then "-alpine" else "" end 4 | }} 5 | 6 | RUN rabbitmq-plugins enable --offline rabbitmq_management 7 | 8 | # make sure the metrics collector is re-enabled (disabled in the base image for Prometheus-style metrics by default) 9 | RUN rm -f /etc/rabbitmq/conf.d/management_agent.disable_metrics_collector.conf 10 | 11 | # extract "rabbitmqadmin" from inside the "rabbitmq_management-X.Y.Z.ez" plugin zipfile 12 | # see https://github.com/docker-library/rabbitmq/issues/207 13 | RUN set -eux; \ 14 | erl -noinput -eval ' \ 15 | { ok, AdminBin } = zip:foldl(fun(FileInArchive, GetInfo, GetBin, Acc) -> \ 16 | case Acc of \ 17 | "" -> \ 18 | case lists:suffix("/rabbitmqadmin", FileInArchive) of \ 19 | true -> GetBin(); \ 20 | false -> Acc \ 21 | end; \ 22 | _ -> Acc \ 23 | end \ 24 | end, "", init:get_plain_arguments()), \ 25 | io:format("~s", [ AdminBin ]), \ 26 | init:stop(). \ 27 | ' -- /plugins/rabbitmq_management-*.ez > /usr/local/bin/rabbitmqadmin; \ 28 | [ -s /usr/local/bin/rabbitmqadmin ]; \ 29 | chmod +x /usr/local/bin/rabbitmqadmin; \ 30 | {{ if env.variant == "alpine" then ( -}} 31 | apk add --no-cache python3; \ 32 | {{ ) else ( -}} 33 | apt-get update; \ 34 | apt-get install -y --no-install-recommends python3; \ 35 | rm -rf /var/lib/apt/lists/*; \ 36 | {{ ) end -}} 37 | rabbitmqadmin --version 38 | 39 | EXPOSE 15671 15672 40 | -------------------------------------------------------------------------------- /Dockerfile-ubuntu.template: -------------------------------------------------------------------------------- 1 | # The official Canonical Ubuntu Bionic image is ideal from a security perspective, 2 | # especially for the enterprises that we, the RabbitMQ team, have to deal with 3 | FROM ubuntu:18.04 4 | 5 | RUN set -eux; \ 6 | apt-get update; \ 7 | apt-get install -y --no-install-recommends \ 8 | # grab gosu for easy step-down from root 9 | gosu \ 10 | ; \ 11 | rm -rf /var/lib/apt/lists/*; \ 12 | # verify that the "gosu" binary works 13 | gosu nobody true 14 | 15 | # Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally 16 | ARG PGP_KEYSERVER=ha.pool.sks-keyservers.net 17 | # If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, 18 | # run the build with a different PGP_KEYSERVER, e.g. docker build --tag rabbitmq:3.8 --build-arg PGP_KEYSERVER=pgpkeys.eu 3.8/ubuntu 19 | # For context, see https://github.com/docker-library/official-images/issues/4252 20 | 21 | ENV OPENSSL_VERSION {{ .openssl.version }} 22 | ENV OPENSSL_SOURCE_SHA256="{{ .openssl.sha256 }}" 23 | # https://www.openssl.org/community/omc.html 24 | ENV OPENSSL_PGP_KEY_IDS="{{ 25 | [ 26 | # Matt Caswell 27 | "8657 ABB2 60F0 56B1 E519 0839 D9C4 D26D 0E60 4491", 28 | 29 | # Mark J. Cox 30 | "5B25 45DA B219 95F4 088C EFAA 36CE E4DE B00C FE33", 31 | 32 | # Paul Dale 33 | "ED23 0BEC 4D4F 2518 B9D7 DF41 F0DB 4D21 C1D3 5231", 34 | 35 | # Tim Hudson 36 | "C1F3 3DD8 CE1D 4CC6 13AF 14DA 9195 C482 41FB F7DD", 37 | 38 | # Richard Levitte 39 | "7953 AC1F BC3D C8B3 B292 393E D5E9 E43F 7DF9 EE8C", 40 | 41 | # Kurt Roeckx 42 | "E5E5 2560 DD91 C556 DDBD A5D0 2064 C536 41C2 5E5D" 43 | ] 44 | # 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?) 45 | | map("0x" + gsub(" "; "")) | join(" ") 46 | }}" 47 | 48 | ENV OTP_VERSION {{ .otp.version }} 49 | # TODO add PGP checking when the feature will be added to Erlang/OTP's build system 50 | # https://erlang.org/pipermail/erlang-questions/2019-January/097067.html 51 | ENV OTP_SOURCE_SHA256="{{ .otp.sha256 }}" 52 | 53 | # Install dependencies required to build Erlang/OTP from source 54 | # https://erlang.org/doc/installation_guide/INSTALL.html 55 | # autoconf: Required to configure Erlang/OTP before compiling 56 | # dpkg-dev: Required to set up host & build type when compiling Erlang/OTP 57 | # gnupg: Required to verify OpenSSL artefacts 58 | # libncurses5-dev: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli 59 | RUN set -eux; \ 60 | \ 61 | savedAptMark="$(apt-mark showmanual)"; \ 62 | apt-get update; \ 63 | apt-get install --yes --no-install-recommends \ 64 | autoconf \ 65 | ca-certificates \ 66 | dpkg-dev \ 67 | gcc \ 68 | gnupg \ 69 | libncurses5-dev \ 70 | make \ 71 | wget \ 72 | ; \ 73 | rm -rf /var/lib/apt/lists/*; \ 74 | \ 75 | OPENSSL_SOURCE_URL="https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz"; \ 76 | OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ 77 | OPENSSL_CONFIG_DIR=/usr/local/etc/ssl; \ 78 | \ 79 | # Required by the crypto & ssl Erlang/OTP applications 80 | wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_SOURCE_URL.asc"; \ 81 | wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz" "$OPENSSL_SOURCE_URL"; \ 82 | export GNUPGHOME="$(mktemp -d)"; \ 83 | for key in $OPENSSL_PGP_KEY_IDS; do \ 84 | gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \ 85 | done; \ 86 | gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \ 87 | gpgconf --kill all; \ 88 | rm -rf "$GNUPGHOME"; \ 89 | echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum --check --strict -; \ 90 | mkdir -p "$OPENSSL_PATH"; \ 91 | tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \ 92 | \ 93 | # Configure OpenSSL for compilation 94 | cd "$OPENSSL_PATH"; \ 95 | # without specifying "--libdir", Erlang will fail during "crypto:supports()" looking for a "pthread_atfork" function that doesn't exist (but only on arm32v7/armhf??) 96 | debMultiarch="$(dpkg-architecture --query DEB_HOST_MULTIARCH)"; \ 97 | # OpenSSL's "config" script uses a lot of "uname"-based target detection... 98 | MACHINE="$(dpkg-architecture --query DEB_BUILD_GNU_CPU)" \ 99 | RELEASE="4.x.y-z" \ 100 | SYSTEM='Linux' \ 101 | BUILD='???' \ 102 | ./config \ 103 | --openssldir="$OPENSSL_CONFIG_DIR" \ 104 | --libdir="lib/$debMultiarch" \ 105 | # 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) 106 | -Wl,-rpath=/usr/local/lib \ 107 | ; \ 108 | # Compile, install OpenSSL, verify that the command-line works & development headers are present 109 | make -j "$(getconf _NPROCESSORS_ONLN)"; \ 110 | make install_sw install_ssldirs; \ 111 | cd ..; \ 112 | rm -rf "$OPENSSL_PATH"*; \ 113 | ldconfig; \ 114 | # use Debian's CA certificates 115 | rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ 116 | ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR"; \ 117 | # smoke test 118 | openssl version; \ 119 | \ 120 | OTP_SOURCE_URL="https://github.com/erlang/otp/releases/download/OTP-$OTP_VERSION/otp_src_$OTP_VERSION.tar.gz"; \ 121 | OTP_PATH="/usr/local/src/otp-$OTP_VERSION"; \ 122 | \ 123 | # Download, verify & extract OTP_SOURCE 124 | mkdir -p "$OTP_PATH"; \ 125 | wget --progress dot:giga --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \ 126 | echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum --check --strict -; \ 127 | tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \ 128 | \ 129 | # Configure Erlang/OTP for compilation, disable unused features & applications 130 | # https://erlang.org/doc/applications.html 131 | # ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation 132 | cd "$OTP_PATH"; \ 133 | export ERL_TOP="$OTP_PATH"; \ 134 | ./otp_build autoconf; \ 135 | CFLAGS="$(dpkg-buildflags --get CFLAGS)"; export CFLAGS; \ 136 | # 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) 137 | export CFLAGS="$CFLAGS -Wl,-rpath=/usr/local/lib"; \ 138 | hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ 139 | buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ 140 | dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ 141 | ./configure \ 142 | --host="$hostArch" \ 143 | --build="$buildArch" \ 144 | --disable-dynamic-ssl-lib \ 145 | --disable-hipe \ 146 | --disable-sctp \ 147 | --disable-silent-rules \ 148 | --enable-clock-gettime \ 149 | --enable-hybrid-heap \ 150 | --enable-kernel-poll \ 151 | --enable-shared-zlib \ 152 | --enable-smp-support \ 153 | --enable-threads \ 154 | --with-microstate-accounting=extra \ 155 | --without-common_test \ 156 | --without-debugger \ 157 | --without-dialyzer \ 158 | --without-diameter \ 159 | --without-edoc \ 160 | --without-erl_docgen \ 161 | --without-erl_interface \ 162 | --without-et \ 163 | --without-eunit \ 164 | --without-ftp \ 165 | --without-hipe \ 166 | --without-jinterface \ 167 | --without-megaco \ 168 | --without-observer \ 169 | --without-odbc \ 170 | --without-reltool \ 171 | --without-ssh \ 172 | --without-tftp \ 173 | --without-wx \ 174 | ; \ 175 | # Compile & install Erlang/OTP 176 | make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ 177 | make install; \ 178 | cd ..; \ 179 | rm -rf \ 180 | "$OTP_PATH"* \ 181 | /usr/local/lib/erlang/lib/*/examples \ 182 | /usr/local/lib/erlang/lib/*/src \ 183 | ; \ 184 | \ 185 | # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies 186 | apt-mark auto '.*' > /dev/null; \ 187 | [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \ 188 | find /usr/local -type f -executable -exec ldd '{}' ';' \ 189 | | awk '/=>/ { print $(NF-1) }' \ 190 | | sort -u \ 191 | | xargs -r dpkg-query --search \ 192 | | cut -d: -f1 \ 193 | | sort -u \ 194 | | xargs -r apt-mark manual \ 195 | ; \ 196 | apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ 197 | \ 198 | # Check that OpenSSL still works after purging build dependencies 199 | openssl version; \ 200 | # Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly 201 | erl -noshell -eval 'io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' 202 | 203 | ENV RABBITMQ_DATA_DIR=/var/lib/rabbitmq 204 | # Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM 205 | RUN set -eux; \ 206 | groupadd --gid 999 --system rabbitmq; \ 207 | useradd --uid 999 --system --home-dir "$RABBITMQ_DATA_DIR" --gid rabbitmq rabbitmq; \ 208 | mkdir -p "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 209 | chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 210 | chmod 777 "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ 211 | ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie 212 | 213 | # Use the latest stable RabbitMQ release (https://www.rabbitmq.com/download.html) 214 | ENV RABBITMQ_VERSION {{ .version }} 215 | # https://www.rabbitmq.com/signatures.html#importing-gpg 216 | ENV RABBITMQ_PGP_KEY_ID="0x0A9AF2115F4687BD29803A206B73A36E6026DFCA" 217 | ENV RABBITMQ_HOME=/opt/rabbitmq 218 | 219 | # Add RabbitMQ to PATH, send all logs to TTY 220 | ENV PATH=$RABBITMQ_HOME/sbin:$PATH \ 221 | RABBITMQ_LOGS=- 222 | 223 | # Install RabbitMQ 224 | RUN set -eux; \ 225 | \ 226 | savedAptMark="$(apt-mark showmanual)"; \ 227 | apt-get update; \ 228 | apt-get install --yes --no-install-recommends \ 229 | ca-certificates \ 230 | gnupg \ 231 | wget \ 232 | xz-utils \ 233 | ; \ 234 | rm -rf /var/lib/apt/lists/*; \ 235 | \ 236 | RABBITMQ_SOURCE_URL="https://github.com/rabbitmq/rabbitmq-server/releases/download/v$RABBITMQ_VERSION/rabbitmq-server-generic-unix-latest-toolchain-$RABBITMQ_VERSION.tar.xz"; \ 237 | RABBITMQ_PATH="/usr/local/src/rabbitmq-$RABBITMQ_VERSION"; \ 238 | \ 239 | wget --progress dot:giga --output-document "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_SOURCE_URL.asc"; \ 240 | wget --progress dot:giga --output-document "$RABBITMQ_PATH.tar.xz" "$RABBITMQ_SOURCE_URL"; \ 241 | \ 242 | export GNUPGHOME="$(mktemp -d)"; \ 243 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$RABBITMQ_PGP_KEY_ID"; \ 244 | gpg --batch --verify "$RABBITMQ_PATH.tar.xz.asc" "$RABBITMQ_PATH.tar.xz"; \ 245 | gpgconf --kill all; \ 246 | rm -rf "$GNUPGHOME"; \ 247 | \ 248 | mkdir -p "$RABBITMQ_HOME"; \ 249 | tar --extract --file "$RABBITMQ_PATH.tar.xz" --directory "$RABBITMQ_HOME" --strip-components 1; \ 250 | rm -rf "$RABBITMQ_PATH"*; \ 251 | # Do not default SYS_PREFIX to RABBITMQ_HOME, leave it empty 252 | grep -qE '^SYS_PREFIX=\$\{RABBITMQ_HOME\}$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 253 | sed -i 's/^SYS_PREFIX=.*$/SYS_PREFIX=/' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 254 | grep -qE '^SYS_PREFIX=$' "$RABBITMQ_HOME/sbin/rabbitmq-defaults"; \ 255 | chown -R rabbitmq:rabbitmq "$RABBITMQ_HOME"; \ 256 | \ 257 | apt-mark auto '.*' > /dev/null; \ 258 | apt-mark manual $savedAptMark; \ 259 | apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ 260 | \ 261 | # verify assumption of no stale cookies 262 | [ ! -e "$RABBITMQ_DATA_DIR/.erlang.cookie" ]; \ 263 | # Ensure RabbitMQ was installed correctly by running a few commands that do not depend on a running server, as the rabbitmq user 264 | # If they all succeed, it's safe to assume that things have been set up correctly 265 | gosu rabbitmq rabbitmqctl help; \ 266 | gosu rabbitmq rabbitmqctl list_ciphers; \ 267 | gosu rabbitmq rabbitmq-plugins list; \ 268 | # no stale cookies 269 | rm "$RABBITMQ_DATA_DIR/.erlang.cookie" 270 | 271 | # Enable Prometheus-style metrics by default (https://github.com/docker-library/rabbitmq/issues/419) 272 | RUN set -eux; \ 273 | rabbitmq-plugins enable --offline rabbitmq_prometheus; \ 274 | echo 'management_agent.disable_metrics_collector = true' > /etc/rabbitmq/conf.d/management_agent.disable_metrics_collector.conf 275 | 276 | # Added for backwards compatibility - users can simply COPY custom plugins to /plugins 277 | RUN ln -sf /opt/rabbitmq/plugins /plugins 278 | 279 | # set home so that any `--user` knows where to put the erlang cookie 280 | ENV HOME $RABBITMQ_DATA_DIR 281 | # Hint that the data (a.k.a. home dir) dir should be separate volume 282 | VOLUME $RABBITMQ_DATA_DIR 283 | 284 | # 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) 285 | # 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 286 | # https://docs.docker.com/samples/library/ubuntu/#locales 287 | ENV LANG=C.UTF-8 LANGUAGE=C.UTF-8 LC_ALL=C.UTF-8 288 | 289 | COPY docker-entrypoint.sh /usr/local/bin/ 290 | ENTRYPOINT ["docker-entrypoint.sh"] 291 | 292 | EXPOSE 4369 5671 5672 15691 15692 25672 293 | CMD ["rabbitmq-server"] 294 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Docker, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included 12 | in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # https://github.com/docker-library/rabbitmq 2 | 3 | ## Maintained by: [the Docker Community](https://github.com/docker-library/rabbitmq) 4 | 5 | This is the Git repo of the [Docker "Official Image"](https://github.com/docker-library/official-images#what-are-official-images) for [`rabbitmq`](https://hub.docker.com/_/rabbitmq/) (not to be confused with any official `rabbitmq` image provided by `rabbitmq` upstream). See [the Docker Hub page](https://hub.docker.com/_/rabbitmq/) for the full readme on how to use this Docker image and for information regarding contributing and issues. 6 | 7 | The [full image description on Docker Hub](https://hub.docker.com/_/rabbitmq/) is generated/maintained over in [the docker-library/docs repository](https://github.com/docker-library/docs), specifically in [the `rabbitmq` directory](https://github.com/docker-library/docs/tree/master/rabbitmq). 8 | 9 | ## See a change merged here that doesn't show up on Docker Hub yet? 10 | 11 | For more information about the full official images change lifecycle, see [the "An image's source changed in Git, now what?" FAQ entry](https://github.com/docker-library/faq#an-images-source-changed-in-git-now-what). 12 | 13 | For outstanding `rabbitmq` image PRs, check [PRs with the "library/rabbitmq" label on the official-images repository](https://github.com/docker-library/official-images/labels/library%2Frabbitmq). For the current "source of truth" for [`rabbitmq`](https://hub.docker.com/_/rabbitmq/), see [the `library/rabbitmq` file in the official-images repository](https://github.com/docker-library/official-images/blob/master/library/rabbitmq). 14 | 15 | --- 16 | 17 | - [![build status badge](https://img.shields.io/github/workflow/status/docker-library/rabbitmq/GitHub%20CI/master?label=GitHub%20CI)](https://github.com/docker-library/rabbitmq/actions?query=workflow%3A%22GitHub+CI%22+branch%3Amaster) 18 | - [![build status badge](https://img.shields.io/jenkins/s/https/doi-janky.infosiftr.net/job/update.sh/job/rabbitmq.svg?label=Automated%20update.sh)](https://doi-janky.infosiftr.net/job/update.sh/job/rabbitmq/) 19 | 20 | | Build | Status | Badges | (per-arch) | 21 | |:-:|:-:|:-:|:-:| 22 | | [![amd64 build status badge](https://img.shields.io/jenkins/s/https/doi-janky.infosiftr.net/job/multiarch/job/amd64/job/rabbitmq.svg?label=amd64)](https://doi-janky.infosiftr.net/job/multiarch/job/amd64/job/rabbitmq/) | [![arm32v6 build status badge](https://img.shields.io/jenkins/s/https/doi-janky.infosiftr.net/job/multiarch/job/arm32v6/job/rabbitmq.svg?label=arm32v6)](https://doi-janky.infosiftr.net/job/multiarch/job/arm32v6/job/rabbitmq/) | [![arm32v7 build status badge](https://img.shields.io/jenkins/s/https/doi-janky.infosiftr.net/job/multiarch/job/arm32v7/job/rabbitmq.svg?label=arm32v7)](https://doi-janky.infosiftr.net/job/multiarch/job/arm32v7/job/rabbitmq/) | [![arm64v8 build status badge](https://img.shields.io/jenkins/s/https/doi-janky.infosiftr.net/job/multiarch/job/arm64v8/job/rabbitmq.svg?label=arm64v8)](https://doi-janky.infosiftr.net/job/multiarch/job/arm64v8/job/rabbitmq/) | 23 | | [![i386 build status badge](https://img.shields.io/jenkins/s/https/doi-janky.infosiftr.net/job/multiarch/job/i386/job/rabbitmq.svg?label=i386)](https://doi-janky.infosiftr.net/job/multiarch/job/i386/job/rabbitmq/) | [![ppc64le build status badge](https://img.shields.io/jenkins/s/https/doi-janky.infosiftr.net/job/multiarch/job/ppc64le/job/rabbitmq.svg?label=ppc64le)](https://doi-janky.infosiftr.net/job/multiarch/job/ppc64le/job/rabbitmq/) | [![s390x build status badge](https://img.shields.io/jenkins/s/https/doi-janky.infosiftr.net/job/multiarch/job/s390x/job/rabbitmq.svg?label=s390x)](https://doi-janky.infosiftr.net/job/multiarch/job/s390x/job/rabbitmq/) | [![put-shared build status badge](https://img.shields.io/jenkins/s/https/doi-janky.infosiftr.net/job/put-shared/job/light/job/rabbitmq.svg?label=put-shared)](https://doi-janky.infosiftr.net/job/put-shared/job/light/job/rabbitmq/) | 24 | 25 | 26 | -------------------------------------------------------------------------------- /apply-templates.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | [ -f versions.json ] # run "versions.sh" first 5 | 6 | cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" 7 | 8 | jqt='.jq-template.awk' 9 | if [ -n "${BASHBREW_SCRIPTS:-}" ]; then 10 | jqt="$BASHBREW_SCRIPTS/jq-template.awk" 11 | elif [ "$BASH_SOURCE" -nt "$jqt" ]; then 12 | wget -qO "$jqt" 'https://github.com/docker-library/bashbrew/raw/5f0c26381fb7cc78b2d217d58007800bdcfbcfa1/scripts/jq-template.awk' 13 | fi 14 | 15 | if [ "$#" -eq 0 ]; then 16 | versions="$(jq -r 'keys | map(@sh) | join(" ")' versions.json)" 17 | eval "set -- $versions" 18 | fi 19 | 20 | generated_warning() { 21 | cat <<-EOH 22 | # 23 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 24 | # 25 | # PLEASE DO NOT EDIT IT DIRECTLY. 26 | # 27 | 28 | EOH 29 | } 30 | 31 | for version; do 32 | export version 33 | 34 | for variant in alpine ubuntu; do 35 | export variant 36 | 37 | echo "processing $version/$variant ..." 38 | 39 | { 40 | generated_warning 41 | gawk -f "$jqt" "Dockerfile-$variant.template" 42 | } > "$version/$variant/Dockerfile" 43 | 44 | cp -a docker-entrypoint.sh "$version/$variant/" 45 | 46 | if [ "$variant" = 'alpine' ]; then 47 | sed -i -e 's/gosu/su-exec/g' "$version/$variant/docker-entrypoint.sh" 48 | fi 49 | 50 | echo "processing $version/$variant/management ..." 51 | 52 | { 53 | generated_warning 54 | gawk -f "$jqt" Dockerfile-management.template 55 | } > "$version/$variant/management/Dockerfile" 56 | done 57 | done 58 | -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eu 3 | 4 | # usage: file_env VAR [DEFAULT] 5 | # ie: file_env 'XYZ_DB_PASSWORD' 'example' 6 | # (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of 7 | # "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) 8 | file_env() { 9 | local var="$1" 10 | local fileVar="${var}_FILE" 11 | local def="${2:-}" 12 | if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then 13 | echo >&2 "error: both $var and $fileVar are set (but are exclusive)" 14 | exit 1 15 | fi 16 | local val="$def" 17 | if [ "${!var:-}" ]; then 18 | val="${!var}" 19 | elif [ "${!fileVar:-}" ]; then 20 | val="$(< "${!fileVar}")" 21 | fi 22 | export "$var"="$val" 23 | unset "$fileVar" 24 | } 25 | 26 | # backwards compatibility for old environment variables 27 | : "${RABBITMQ_SSL_CERTFILE:=${RABBITMQ_SSL_CERT_FILE:-}}" 28 | : "${RABBITMQ_SSL_KEYFILE:=${RABBITMQ_SSL_KEY_FILE:-}}" 29 | : "${RABBITMQ_SSL_CACERTFILE:=${RABBITMQ_SSL_CA_FILE:-}}" 30 | 31 | # "management" SSL config should default to using the same certs 32 | : "${RABBITMQ_MANAGEMENT_SSL_CACERTFILE:=$RABBITMQ_SSL_CACERTFILE}" 33 | : "${RABBITMQ_MANAGEMENT_SSL_CERTFILE:=$RABBITMQ_SSL_CERTFILE}" 34 | : "${RABBITMQ_MANAGEMENT_SSL_KEYFILE:=$RABBITMQ_SSL_KEYFILE}" 35 | 36 | # Allowed env vars that will be read from mounted files (i.e. Docker Secrets): 37 | fileEnvKeys=( 38 | default_user 39 | default_pass 40 | ) 41 | 42 | # https://www.rabbitmq.com/configure.html 43 | sslConfigKeys=( 44 | cacertfile 45 | certfile 46 | depth 47 | fail_if_no_peer_cert 48 | keyfile 49 | verify 50 | ) 51 | managementConfigKeys=( 52 | "${sslConfigKeys[@]/#/ssl_}" 53 | ) 54 | rabbitConfigKeys=( 55 | default_pass 56 | default_user 57 | default_vhost 58 | vm_memory_high_watermark 59 | ) 60 | fileConfigKeys=( 61 | management_ssl_cacertfile 62 | management_ssl_certfile 63 | management_ssl_keyfile 64 | ssl_cacertfile 65 | ssl_certfile 66 | ssl_keyfile 67 | ) 68 | allConfigKeys=( 69 | "${managementConfigKeys[@]/#/management_}" 70 | "${rabbitConfigKeys[@]}" 71 | "${sslConfigKeys[@]/#/ssl_}" 72 | ) 73 | 74 | declare -A configDefaults=( 75 | [management_ssl_fail_if_no_peer_cert]='false' 76 | [management_ssl_verify]='verify_none' 77 | 78 | [ssl_fail_if_no_peer_cert]='true' 79 | [ssl_verify]='verify_peer' 80 | ) 81 | 82 | # allow the container to be started with `--user` 83 | if [[ "$1" == rabbitmq* ]] && [ "$(id -u)" = '0' ]; then 84 | # this needs to happen late enough that we have the SSL config 85 | # https://github.com/docker-library/rabbitmq/issues/283 86 | for conf in "${allConfigKeys[@]}"; do 87 | var="RABBITMQ_${conf^^}" 88 | val="${!var:-}" 89 | [ -n "$val" ] || continue 90 | case "$conf" in 91 | *_ssl_*file | ssl_*file ) 92 | if [ -f "$val" ] && ! gosu rabbitmq test -r "$val"; then 93 | newFile="/tmp/rabbitmq-ssl/$conf.pem" 94 | echo >&2 95 | echo >&2 "WARNING: '$val' ($var) is not readable by rabbitmq ($(id rabbitmq)); copying to '$newFile'" 96 | echo >&2 97 | cat "$val" > "$newFile" 98 | chown rabbitmq "$newFile" 99 | chmod 0400 "$newFile" 100 | eval 'export '$var'="$newFile"' 101 | fi 102 | ;; 103 | esac 104 | done 105 | 106 | if [ "$1" = 'rabbitmq-server' ]; then 107 | find /var/lib/rabbitmq \! -user rabbitmq -exec chown rabbitmq '{}' + 108 | fi 109 | 110 | exec gosu rabbitmq "$BASH_SOURCE" "$@" 111 | fi 112 | 113 | haveConfig= 114 | haveSslConfig= 115 | haveManagementSslConfig= 116 | for fileEnvKey in "${fileEnvKeys[@]}"; do file_env "RABBITMQ_${fileEnvKey^^}"; done 117 | for conf in "${allConfigKeys[@]}"; do 118 | var="RABBITMQ_${conf^^}" 119 | val="${!var:-}" 120 | if [ "$val" ]; then 121 | if [ "${configDefaults[$conf]:-}" ] && [ "${configDefaults[$conf]}" = "$val" ]; then 122 | # if the value set is the same as the default, treat it as if it isn't set 123 | continue 124 | fi 125 | haveConfig=1 126 | case "$conf" in 127 | ssl_*) haveSslConfig=1 ;; 128 | management_ssl_*) haveManagementSslConfig=1 ;; 129 | esac 130 | fi 131 | done 132 | if [ "$haveSslConfig" ]; then 133 | missing=() 134 | for sslConf in cacertfile certfile keyfile; do 135 | var="RABBITMQ_SSL_${sslConf^^}" 136 | val="${!var}" 137 | if [ -z "$val" ]; then 138 | missing+=( "$var" ) 139 | fi 140 | done 141 | if [ "${#missing[@]}" -gt 0 ]; then 142 | { 143 | echo 144 | echo 'error: SSL requested, but missing required configuration' 145 | for miss in "${missing[@]}"; do 146 | echo " - $miss" 147 | done 148 | echo 149 | } >&2 150 | exit 1 151 | fi 152 | fi 153 | missingFiles=() 154 | for conf in "${fileConfigKeys[@]}"; do 155 | var="RABBITMQ_${conf^^}" 156 | val="${!var}" 157 | if [ "$val" ] && [ ! -f "$val" ]; then 158 | missingFiles+=( "$val ($var)" ) 159 | fi 160 | done 161 | if [ "${#missingFiles[@]}" -gt 0 ]; then 162 | { 163 | echo 164 | echo 'error: files specified, but missing' 165 | for miss in "${missingFiles[@]}"; do 166 | echo " - $miss" 167 | done 168 | echo 169 | } >&2 170 | exit 1 171 | fi 172 | 173 | # set defaults for missing values (but only after we're done with all our checking so we don't throw any of that off) 174 | for conf in "${!configDefaults[@]}"; do 175 | default="${configDefaults[$conf]}" 176 | var="RABBITMQ_${conf^^}" 177 | [ -z "${!var:-}" ] || continue 178 | eval "export $var=\"\$default\"" 179 | done 180 | 181 | # if long and short hostnames are not the same, use long hostnames 182 | if [ "$(hostname)" != "$(hostname -s)" ]; then 183 | : "${RABBITMQ_USE_LONGNAME:=true}" 184 | fi 185 | 186 | if [ "${RABBITMQ_ERLANG_COOKIE:-}" ]; then 187 | cookieFile='/var/lib/rabbitmq/.erlang.cookie' 188 | if [ -e "$cookieFile" ]; then 189 | if [ "$(cat "$cookieFile" 2>/dev/null)" != "$RABBITMQ_ERLANG_COOKIE" ]; then 190 | echo >&2 191 | echo >&2 "warning: $cookieFile contents do not match RABBITMQ_ERLANG_COOKIE" 192 | echo >&2 193 | fi 194 | else 195 | echo "$RABBITMQ_ERLANG_COOKIE" > "$cookieFile" 196 | fi 197 | chmod 600 "$cookieFile" 198 | fi 199 | 200 | configBase="${RABBITMQ_CONFIG_FILE:-/etc/rabbitmq/rabbitmq}" 201 | oldConfigFile="$configBase.config" 202 | newConfigFile="$configBase.conf" 203 | 204 | shouldWriteConfig="$haveConfig" 205 | if [ -n "$shouldWriteConfig" ] && ! touch "$newConfigFile"; then 206 | # config file exists but it isn't writeable (likely read-only mount, such as Kubernetes configMap) 207 | export RABBITMQ_CONFIG_FILE='/tmp/rabbitmq.conf' 208 | cp "$newConfigFile" "$RABBITMQ_CONFIG_FILE" 209 | echo >&2 210 | echo >&2 "WARNING: '$newConfigFile' is not writable, but environment variables have been provided which request that we write to it" 211 | echo >&2 " We have copied it to '$RABBITMQ_CONFIG_FILE' so it can be amended to work around the problem, but it is recommended that the read-only source file should be modified and the environment variables removed instead." 212 | echo >&2 213 | newConfigFile="$RABBITMQ_CONFIG_FILE" 214 | fi 215 | if [ -n "$shouldWriteConfig" ] && [ -f "$oldConfigFile" ]; then 216 | { 217 | echo "error: Docker configuration environment variables specified, but old-style (Erlang syntax) configuration file '$oldConfigFile' exists" 218 | echo " Suggested fixes: (choose one)" 219 | echo " - remove '$oldConfigFile'" 220 | echo " - remove any Docker-specific 'RABBITMQ_...' environment variables" 221 | echo " - convert '$oldConfigFile' to the newer sysctl format ('$newConfigFile'); see https://www.rabbitmq.com/configure.html#config-file" 222 | } >&2 223 | exit 1 224 | fi 225 | if [ -z "$shouldWriteConfig" ] && [ ! -f "$oldConfigFile" ] && [ ! -f "$newConfigFile" ]; then 226 | # no config files, we should write one 227 | shouldWriteConfig=1 228 | fi 229 | 230 | # http://stackoverflow.com/a/2705678/433558 231 | sed_escape_lhs() { 232 | echo "$@" | sed -e 's/[]\/$*.^|[]/\\&/g' 233 | } 234 | sed_escape_rhs() { 235 | echo "$@" | sed -e 's/[\/&]/\\&/g' 236 | } 237 | rabbit_set_config() { 238 | local key="$1"; shift 239 | local val="$1"; shift 240 | 241 | [ -e "$newConfigFile" ] || touch "$newConfigFile" 242 | 243 | local sedKey="$(sed_escape_lhs "$key")" 244 | local sedVal="$(sed_escape_rhs "$val")" 245 | sed -ri \ 246 | "s/^[[:space:]]*(${sedKey}[[:space:]]*=[[:space:]]*)\S.*\$/\1${sedVal}/" \ 247 | "$newConfigFile" 248 | if ! grep -qE "^${sedKey}[[:space:]]*=" "$newConfigFile"; then 249 | sed -i -e '$a\' "$newConfigFile" # https://github.com/docker-library/rabbitmq/issues/456#issuecomment-752251872 (https://unix.stackexchange.com/a/31955/153467) 250 | echo "$key = $val" >> "$newConfigFile" 251 | fi 252 | } 253 | rabbit_comment_config() { 254 | local key="$1"; shift 255 | 256 | [ -e "$newConfigFile" ] || touch "$newConfigFile" 257 | 258 | local sedKey="$(sed_escape_lhs "$key")" 259 | sed -ri \ 260 | "s/^[[:space:]]*#?[[:space:]]*(${sedKey}[[:space:]]*=[[:space:]]*\S.*)\$/# \1/" \ 261 | "$newConfigFile" 262 | } 263 | rabbit_env_config() { 264 | local prefix="$1"; shift 265 | 266 | local conf 267 | for conf; do 268 | local var="rabbitmq${prefix:+_$prefix}_$conf" 269 | var="${var^^}" 270 | 271 | local key="$conf" 272 | case "$prefix" in 273 | ssl) key="ssl_options.$key" ;; 274 | management_ssl) key="management.ssl.$key" ;; 275 | esac 276 | 277 | local val="${!var:-}" 278 | local rawVal="$val" 279 | case "$conf" in 280 | fail_if_no_peer_cert) 281 | case "${val,,}" in 282 | false|no|0|'') rawVal='false' ;; 283 | true|yes|1|*) rawVal='true' ;; 284 | esac 285 | ;; 286 | 287 | vm_memory_high_watermark) continue ;; # handled separately 288 | esac 289 | 290 | if [ -n "$rawVal" ]; then 291 | rabbit_set_config "$key" "$rawVal" 292 | else 293 | rabbit_comment_config "$key" 294 | fi 295 | done 296 | } 297 | 298 | if [ "$1" = 'rabbitmq-server' ] && [ "$shouldWriteConfig" ]; then 299 | rabbit_set_config 'loopback_users.guest' 'false' 300 | 301 | # determine whether to set "vm_memory_high_watermark" (based on cgroups) 302 | memTotalKb= 303 | if [ -r /proc/meminfo ]; then 304 | memTotalKb="$(awk -F ':? +' '$1 == "MemTotal" { print $2; exit }' /proc/meminfo)" 305 | fi 306 | memLimitB= 307 | if [ -r /sys/fs/cgroup/memory/memory.limit_in_bytes ]; then 308 | # "18446744073709551615" is a valid value for "memory.limit_in_bytes", which is too big for Bash math to handle 309 | # "$(( 18446744073709551615 / 1024 ))" = 0; "$(( 18446744073709551615 * 40 / 100 ))" = 0 310 | memLimitB="$(awk -v totKb="$memTotalKb" '{ 311 | limB = $0; 312 | limKb = limB / 1024; 313 | if (!totKb || limKb < totKb) { 314 | printf "%.0f\n", limB; 315 | } 316 | }' /sys/fs/cgroup/memory/memory.limit_in_bytes)" 317 | fi 318 | if [ -n "$memLimitB" ]; then 319 | # if we have a cgroup memory limit, let's inform RabbitMQ of what it is (so it can calculate vm_memory_high_watermark properly) 320 | # https://github.com/rabbitmq/rabbitmq-server/pull/1234 321 | rabbit_set_config 'total_memory_available_override_value' "$memLimitB" 322 | fi 323 | # https://www.rabbitmq.com/memory.html#memsup-usage 324 | if [ "${RABBITMQ_VM_MEMORY_HIGH_WATERMARK:-}" ]; then 325 | # https://github.com/docker-library/rabbitmq/pull/105#issuecomment-242165822 326 | vmMemoryHighWatermark="$( 327 | echo "$RABBITMQ_VM_MEMORY_HIGH_WATERMARK" | awk ' 328 | /^[0-9]*[.][0-9]+$|^[0-9]+([.][0-9]+)?%$/ { 329 | perc = $0; 330 | if (perc ~ /%$/) { 331 | gsub(/%$/, "", perc); 332 | perc = perc / 100; 333 | } 334 | if (perc > 1.0 || perc < 0.0) { 335 | printf "error: invalid percentage for vm_memory_high_watermark: %s (must be >= 0%%, <= 100%%)\n", $0 > "/dev/stderr"; 336 | exit 1; 337 | } 338 | printf "vm_memory_high_watermark.relative %0.03f\n", perc; 339 | next; 340 | } 341 | /^[0-9]+$/ { 342 | printf "vm_memory_high_watermark.absolute %s\n", $0; 343 | next; 344 | } 345 | /^[0-9]+([.][0-9]+)?[a-zA-Z]+$/ { 346 | printf "vm_memory_high_watermark.absolute %s\n", $0; 347 | next; 348 | } 349 | { 350 | printf "error: unexpected input for vm_memory_high_watermark: %s\n", $0; 351 | exit 1; 352 | } 353 | ' 354 | )" 355 | if [ "$vmMemoryHighWatermark" ]; then 356 | vmMemoryHighWatermarkKey="${vmMemoryHighWatermark%% *}" 357 | vmMemoryHighWatermarkVal="${vmMemoryHighWatermark#$vmMemoryHighWatermarkKey }" 358 | rabbit_set_config "$vmMemoryHighWatermarkKey" "$vmMemoryHighWatermarkVal" 359 | case "$vmMemoryHighWatermarkKey" in 360 | # make sure we only set one or the other 361 | 'vm_memory_high_watermark.absolute') rabbit_comment_config 'vm_memory_high_watermark.relative' ;; 362 | 'vm_memory_high_watermark.relative') rabbit_comment_config 'vm_memory_high_watermark.absolute' ;; 363 | esac 364 | fi 365 | fi 366 | 367 | if [ "$haveSslConfig" ]; then 368 | rabbit_set_config 'listeners.ssl.default' 5671 369 | rabbit_env_config 'ssl' "${sslConfigKeys[@]}" 370 | else 371 | rabbit_set_config 'listeners.tcp.default' 5672 372 | fi 373 | 374 | rabbit_env_config '' "${rabbitConfigKeys[@]}" 375 | 376 | # if management plugin is installed, generate config for it 377 | # https://www.rabbitmq.com/management.html#configuration 378 | if [ "$(rabbitmq-plugins list -q -m -e rabbitmq_management)" ]; then 379 | if [ "$haveManagementSslConfig" ]; then 380 | rabbit_set_config 'management.ssl.port' 15671 381 | rabbit_env_config 'management_ssl' "${sslConfigKeys[@]}" 382 | else 383 | rabbit_set_config 'management.tcp.port' 15672 384 | fi 385 | 386 | # if definitions file exists, then load it 387 | # https://www.rabbitmq.com/management.html#load-definitions 388 | managementDefinitionsFile='/etc/rabbitmq/definitions.json' 389 | if [ -f "$managementDefinitionsFile" ]; then 390 | # We use `load_definitions` (the built-in setting as of 3.8.2+) instead 391 | # of `management.load_definitions`. 392 | # See https://github.com/docker-library/rabbitmq/issues/429 for details. 393 | rabbit_set_config 'load_definitions' "$managementDefinitionsFile" 394 | fi 395 | fi 396 | fi 397 | 398 | combinedSsl='/tmp/rabbitmq-ssl/combined.pem' 399 | if [ "$haveSslConfig" ] && [[ "$1" == rabbitmq* ]] && [ ! -f "$combinedSsl" ]; then 400 | # Create combined cert 401 | { 402 | cat "$RABBITMQ_SSL_CERTFILE" 403 | echo # https://github.com/docker-library/rabbitmq/issues/357#issuecomment-517755647 404 | cat "$RABBITMQ_SSL_KEYFILE" 405 | } > "$combinedSsl" 406 | chmod 0400 "$combinedSsl" 407 | fi 408 | if [ "$haveSslConfig" ] && [ -f "$combinedSsl" ]; then 409 | # More ENV vars for make clustering happiness 410 | # we don't handle clustering in this script, but these args should ensure 411 | # clustered SSL-enabled members will talk nicely 412 | export ERL_SSL_PATH="$(erl -eval 'io:format("~p", [code:lib_dir(ssl, ebin)]),halt().' -noshell)" 413 | sslErlArgs="-pa $ERL_SSL_PATH -proto_dist inet_tls -ssl_dist_opt server_certfile $combinedSsl -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true" 414 | export RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="${RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS:-} $sslErlArgs" 415 | export RABBITMQ_CTL_ERL_ARGS="${RABBITMQ_CTL_ERL_ARGS:-} $sslErlArgs" 416 | fi 417 | 418 | exec "$@" 419 | -------------------------------------------------------------------------------- /generate-stackbrew-library.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | declare -A aliases=( 5 | [3.8]='3 latest' 6 | ) 7 | defaultVariant='ubuntu' 8 | 9 | self="$(basename "$BASH_SOURCE")" 10 | cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" 11 | 12 | if [ "$#" -eq 0 ]; then 13 | versions="$(jq -r 'keys | map(@sh) | join(" ")' versions.json)" 14 | eval "set -- $versions" 15 | fi 16 | 17 | # sort version numbers with highest first 18 | IFS=$'\n'; set -- $(sort -rV <<<"$*"); unset IFS 19 | 20 | # get the most recent commit which modified any of "$@" 21 | fileCommit() { 22 | git log -1 --format='format:%H' HEAD -- "$@" 23 | } 24 | 25 | # get the most recent commit which modified "$1/Dockerfile" or any file COPY'd from "$1/Dockerfile" 26 | dirCommit() { 27 | local dir="$1"; shift 28 | ( 29 | cd "$dir" 30 | fileCommit \ 31 | Dockerfile \ 32 | $(git show HEAD:./Dockerfile | awk ' 33 | toupper($1) == "COPY" { 34 | for (i = 2; i < NF; i++) { 35 | print $i 36 | } 37 | } 38 | ') 39 | ) 40 | } 41 | 42 | getArches() { 43 | local repo="$1"; shift 44 | local officialImagesUrl='https://github.com/docker-library/official-images/raw/master/library/' 45 | 46 | eval "declare -g -A parentRepoToArches=( $( 47 | find -name 'Dockerfile' -exec awk ' 48 | toupper($1) == "FROM" && $2 !~ /^('"$repo"'|scratch|.*\/.*)(:|$)/ { 49 | print "'"$officialImagesUrl"'" $2 50 | } 51 | ' '{}' + \ 52 | | sort -u \ 53 | | xargs bashbrew cat --format '[{{ .RepoName }}:{{ .TagName }}]="{{ join " " .TagEntry.Architectures }}"' 54 | ) )" 55 | } 56 | getArches 'rabbitmq' 57 | 58 | cat <<-EOH 59 | # this file is generated via https://github.com/docker-library/rabbitmq/blob/$(fileCommit "$self")/$self 60 | 61 | Maintainers: Tianon Gravi (@tianon), 62 | Joseph Ferguson (@yosifkit) 63 | GitRepo: https://github.com/docker-library/rabbitmq.git 64 | EOH 65 | 66 | # prints "$2$1$3$1...$N" 67 | join() { 68 | local sep="$1"; shift 69 | local out; printf -v out "${sep//%/%%}%s" "$@" 70 | echo "${out#$sep}" 71 | } 72 | 73 | for version; do 74 | export version 75 | rcVersion="${version%-rc}" 76 | 77 | fullVersion="$(jq -r '.[env.version].version' versions.json)" 78 | 79 | # if this is a "-rc" release, let's make sure the release it contains isn't already GA (and thus something we should not publish anymore) 80 | export rcVersion 81 | if [ "$rcVersion" != "$version" ] && rcFullVersion="$(jq -r '.[env.rcVersion].version // ""' versions.json)" && [ -n "$rcFullVersion" ]; then 82 | latestVersion="$({ echo "$fullVersion"; echo "$rcFullVersion"; } | sort -V | tail -1)" 83 | if [[ "$fullVersion" == "$rcFullVersion"* ]] || [ "$latestVersion" = "$rcFullVersion" ]; then 84 | # "x.y.z-rc1" == x.y.z* 85 | continue 86 | fi 87 | fi 88 | 89 | versionAliases=() 90 | if [ "$version" = "$rcVersion" ]; then 91 | while [ "$fullVersion" != "$version" -a "${fullVersion%[.-]*}" != "$fullVersion" ]; do 92 | versionAliases+=( $fullVersion ) 93 | fullVersion="${fullVersion%[.-]*}" 94 | done 95 | else 96 | versionAliases+=( $fullVersion ) 97 | fi 98 | versionAliases+=( 99 | $version 100 | ${aliases[$version]:-} 101 | ) 102 | 103 | for variant in ubuntu alpine; do 104 | dir="$version/$variant" 105 | commit="$(dirCommit "$dir")" 106 | 107 | if [ "$variant" = "$defaultVariant" ]; then 108 | variantAliases=( "${versionAliases[@]}" ) 109 | else 110 | variantAliases=( "${versionAliases[@]/%/-$variant}" ) 111 | variantAliases=( "${variantAliases[@]//latest-/}" ) 112 | fi 113 | 114 | variantParent="$(awk 'toupper($1) == "FROM" { print $2 }' "$dir/Dockerfile")" 115 | variantArches="${parentRepoToArches[$variantParent]}" 116 | 117 | echo 118 | cat <<-EOE 119 | Tags: $(join ', ' "${variantAliases[@]}") 120 | Architectures: $(join ', ' $variantArches) 121 | GitCommit: $commit 122 | Directory: $dir 123 | EOE 124 | 125 | for subVariant in management; do 126 | subDir="$dir/$subVariant" 127 | commit="$(dirCommit "$subDir")" 128 | 129 | subVariantAliases=( "${versionAliases[@]/%/-$subVariant}" ) 130 | subVariantAliases=( "${subVariantAliases[@]//latest-/}" ) 131 | 132 | if [ "$variant" != "$defaultVariant" ]; then 133 | subVariantAliases=( "${subVariantAliases[@]/%/-$variant}" ) 134 | fi 135 | 136 | echo 137 | cat <<-EOE 138 | Tags: $(join ', ' "${subVariantAliases[@]}") 139 | Architectures: $(join ', ' $variantArches) 140 | GitCommit: $commit 141 | Directory: $subDir 142 | EOE 143 | done 144 | done 145 | done 146 | -------------------------------------------------------------------------------- /update.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" 5 | 6 | ./versions.sh "$@" 7 | ./apply-templates.sh "$@" 8 | -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "3.8": { 3 | "openssl": { 4 | "sha256": "aaf2fcb575cdf6491b98ab4829abf78a3dec8402b8b81efc8f23c00d443981bf", 5 | "version": "1.1.1j" 6 | }, 7 | "otp": { 8 | "sha256": "0b1ca7d60f4f5a70b56cd0bef77cec2087a53a9a1812d5276a8cd4ce1acfa962", 9 | "version": "23.2.5" 10 | }, 11 | "version": "3.8.12" 12 | }, 13 | "3.8-rc": { 14 | "openssl": { 15 | "sha256": "aaf2fcb575cdf6491b98ab4829abf78a3dec8402b8b81efc8f23c00d443981bf", 16 | "version": "1.1.1j" 17 | }, 18 | "otp": { 19 | "sha256": "0b1ca7d60f4f5a70b56cd0bef77cec2087a53a9a1812d5276a8cd4ce1acfa962", 20 | "version": "23.2.5" 21 | }, 22 | "version": "3.8.12-rc.3" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /versions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # https://www.rabbitmq.com/which-erlang.html ("Maximum supported Erlang/OTP") 5 | declare -A otpMajors=( 6 | [3.8]='23' 7 | ) 8 | 9 | # https://www.openssl.org/policies/releasestrat.html 10 | # https://www.openssl.org/source/ 11 | declare -A opensslMajors=( 12 | [3.8]='1.1' 13 | ) 14 | 15 | cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" 16 | 17 | versions=( "$@" ) 18 | if [ ${#versions[@]} -eq 0 ]; then 19 | versions=( */ ) 20 | json='{}' 21 | else 22 | json="$(< versions.json)" 23 | fi 24 | versions=( "${versions[@]%/}" ) 25 | 26 | for version in "${versions[@]}"; do 27 | export version 28 | 29 | rcVersion="${version%-rc}" 30 | rcGrepV='-v' 31 | if [ "$rcVersion" != "$version" ]; then 32 | rcGrepV= 33 | fi 34 | rcGrepV+=' -E' 35 | rcGrepExpr='beta|milestone|rc' 36 | 37 | githubTags=( $( 38 | git ls-remote --tags https://github.com/rabbitmq/rabbitmq-server.git \ 39 | "refs/tags/v${rcVersion}"{'','.*','-*','^*'} \ 40 | | cut -d'/' -f3- \ 41 | | cut -d'^' -f1 \ 42 | | grep $rcGrepV -- "$rcGrepExpr" \ 43 | | sort -urV 44 | ) ) 45 | 46 | fullVersion= 47 | githubTag= 48 | for possibleTag in "${githubTags[@]}"; do 49 | fullVersion="$( 50 | wget -qO- "https://github.com/rabbitmq/rabbitmq-server/releases/tag/$possibleTag" \ 51 | | grep -oE "/rabbitmq-server-generic-unix-${rcVersion}([.-].+)?[.]tar[.]xz" \ 52 | | head -1 \ 53 | | sed -r "s/^.*(${rcVersion}.*)[.]tar[.]xz/\1/" \ 54 | || : 55 | )" 56 | if [ -n "$fullVersion" ]; then 57 | githubTag="$possibleTag" 58 | break 59 | fi 60 | done 61 | if [ -z "$fullVersion" ] || [ -z "$githubTag" ]; then 62 | echo >&2 "warning: failed to get full version for '$version'; skipping" 63 | continue 64 | fi 65 | export fullVersion 66 | 67 | otpMajor="${otpMajors[$rcVersion]}" 68 | otpVersions=( $( 69 | git ls-remote --tags https://github.com/erlang/otp.git \ 70 | "refs/tags/OTP-$otpMajor.*"\ 71 | | cut -d'/' -f3- \ 72 | | cut -d'^' -f1 \ 73 | | cut -d- -f2- \ 74 | | sort -urV 75 | ) ) 76 | otpVersion= 77 | for possibleVersion in "${otpVersions[@]}"; do 78 | if otpSourceSha256="$( 79 | wget -qO- "https://github.com/erlang/otp/releases/download/OTP-$possibleVersion/SHA256.txt" \ 80 | | awk -v v="$possibleVersion" '$2 == "otp_src_" v ".tar.gz" { print $1 }' 81 | )"; then 82 | otpVersion="$possibleVersion" 83 | break 84 | fi 85 | done 86 | if [ -z "$otpVersion" ]; then 87 | echo >&2 "warning: failed to get Erlang/OTP version for '$version' ($fullVersion); skipping" 88 | continue 89 | fi 90 | export otpVersion otpSourceSha256 91 | 92 | opensslMajor="${opensslMajors[$rcVersion]}" 93 | opensslVersion="$( 94 | wget -qO- 'https://www.openssl.org/source/' \ 95 | | grep -oE 'href="openssl-'"$opensslMajor"'[^"]+[.]tar[.]gz"' \ 96 | | sed -e 's/^href="openssl-//' -e 's/[.]tar[.]gz"//' \ 97 | | sort -uV \ 98 | | tail -1 99 | )" 100 | if [ -z "$opensslVersion" ]; then 101 | echo >&2 "warning: failed to get OpenSSL version for '$version' ($fullVersion); skipping" 102 | continue 103 | fi 104 | opensslSourceSha256="$(wget -qO- "https://www.openssl.org/source/openssl-$opensslVersion.tar.gz.sha256")" 105 | export opensslVersion opensslSourceSha256 106 | 107 | echo "$version: $fullVersion (otp $otpVersion, openssl $opensslVersion)" 108 | 109 | json="$( 110 | jq <<<"$json" -c ' 111 | .[env.version] = { 112 | version: env.fullVersion, 113 | openssl: { 114 | version: env.opensslVersion, 115 | sha256: env.opensslSourceSha256, 116 | }, 117 | otp: { 118 | version: env.otpVersion, 119 | sha256: env.otpSourceSha256, 120 | }, 121 | } 122 | ' 123 | )" 124 | done 125 | 126 | jq <<<"$json" -S . > versions.json 127 | --------------------------------------------------------------------------------