Deploying RabbitMQ With Docker
Below is a BASH script you can use to deploy your own RabbitMQ server using docker. There are many different ways to configure your deployment, but this is a broad generic method that will:
- Deploy with the web interface to manage your server.
- Specify a username and password for managing the server.
- Use a volume to keep state across containers being created/destroyed.
- Uses port 80 for the web interface so that you can just go to the hostname in your browser without having to enter a port number.
Server Requirements
- 1 vCPU
- 512 MB of RAM
- Docker installed on the server.
#!/bin/bash
# Settings
CONTAINER_NAME="rabbitmq-container"
DEFAULT_USER="root"
DEFAULT_PASSWORD="myPassword"
CLUSTER_COOKIE="hello world"
HOSTNAME="rabbitmq.mydomain.com"
# Don't change below this line.
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
docker kill $CONTAINER_NAME
docker rm $CONTAINER_NAME
docker run -d \
--restart=always \
--hostname $HOSTNAME \
--name $CONTAINER_NAME \
-p 4369:4369 \
-p 5671:5671 \
-p 5672:5672 \
-p 443:15671 \
-p 80:15672 \
-p 25672:25672 \
-p 15691:15691 \
-p 15692:15692 \
-e RABBITMQ_ERLANG_COOKIE="$CLUSTER_COOKIE" \
-e RABBITMQ_DEFAULT_USER="$DEFAULT_USER" \
-e RABBITMQ_DEFAULT_PASS="$DEFAULT_PASSWORD" \
-v $DIR/rabbitmq-state:/var/lib/rabbitmq \
rabbitmq:3.13-management
Docker Compose
If you wish to deploy through Docker Compose, then here is an example file:
services:
rabbitmq:
image: rabbitmq:3.13-management
hostname: ${HOSTNAME}
container_name: rabbitmq
restart: always
ports:
- "4369:4369" # empd - peer discovery service
- "5671:5671" # TLS AMQP 0-9-1 and AMQP 1.0 clients
- "5672:5672" # Plain AMQP 0-9-1 and AMQP 1.0 clients
- "443:15671" # management HTTPS port
- "80:15672" # management HTTP port
- "25672:25672" # used for inter-node and CLI tools communication (Erlang distribution server port)
- "15691:15691" # prometheus metrics HTTPS port
- "15692:15692" # prometheus metrics HTTP port
volumes:
- rabbitmq-data:/var/lib/rabbitmq
environment:
- RABBITMQ_ERLANG_COOKIE=${CLUSTER_COOKIE}
- RABBITMQ_DEFAULT_USER=${DEFAULT_USER}
- RABBITMQ_DEFAULT_PASS=${DEFAULT_PASSWORD}
volumes:
rabbitmq-data:
driver: local
Just be sure to create a .env
file with the following variables (filling in the values).
COMPOSE_PROJECT_NAME="rabbitmq"
CLUSTER_COOKIE=""
DEFAULT_USER=""
DEFAULT_PASSWORD=""
Optional - Nginx Proxy Configuration
If you want to have an Nginx proxy handle the TLS certificate termination for your management UI, you can use the following config:
server {
listen 80;
server_name rabbitmq.mydomain.com;
access_log /var/log/nginx/access.log;
return 302 https://rabbitmq.mydomain.com$request_uri;
}
server {
listen 443 ssl;
server_name rabbitmq.mydomain.com;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers RC4:HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
keepalive_timeout 60;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
real_ip_header X-Forwarded-For;
proxy_pass http://192.168.xxx.xxx;
}
}
proxy_pass
value, as well as update the server_name
.
Optional - Adding TLS To RabbitMQ Management Interface
If you don't want to use a reverse proxy, and want to add TLS certificates to RabbitMQ's management interaface directly, one can do so by adding a configuration file to RabbitMQ that tells it that you wish to do this, and telling it where the certificates are.
Firstly, we need to create the relevant folders for our TLS/SSL certificates and the configuration file:
mkdir -p ./volumes/configs
mkdir -p ./volumes/ssl
Then copy/paste the certificate files into the ssl folder with the names:
- chain.pem - the certificate authority file.
- cert.pem - the site certificate file (on its own, not bundlded with the chain/ca).
- privkey.pem - the private key
Finally, create the RabbitMQ configuration file:
editor ./volumes/configs/rabbitmq.conf
... and give it the following content:
## allow access to the guest user from anywhere on the network
## https://www.rabbitmq.com/access-control.html#loopback-users
## https://www.rabbitmq.com/production-checklist.html#users
loopback_users.guest = false
## Send all logs to stdout/TTY. Necessary to see logs when running via
## a container
log.console = true
# Specify the plain HTTP port for the management interface
management.tcp.port = 15672
# Specify the TLS port for the management interface
management.ssl.port = 15671
# A new style format snippet. This format is used by rabbitmq.conf files.
management.ssl.cacertfile = /etc/rabbitmq/ssl/chain.pem
management.ssl.certfile = /etc/rabbitmq/ssl/cert.pem
management.ssl.keyfile = /etc/rabbitmq/ssl/privkey.pem
Then update your docker-compose file to be like so:
services:
rabbitmq:
image: rabbitmq:3.13-management
hostname: ${HOSTNAME}
container_name: rabbitmq
restart: always
ports:
- "4369:4369" # empd - peer discovery service
- "5671:5671" # TLS AMQP 0-9-1 and AMQP 1.0 clients
- "5672:5672" # Plain AMQP 0-9-1 and AMQP 1.0 clients
- "443:15671" # management HTTPS port
- "80:15672" # management HTTP port
- "25672:25672" # used for inter-node and CLI tools communication (Erlang distribution server port)
- "15691:15691" # prometheus metrics HTTPS port
- "15692:15692" # prometheus metrics HTTP port
volumes:
- ./volumes/rabbitmq-data:/var/lib/rabbitmq
- ./volumes/configs:/etc/rabbitmq/conf.d:ro
- ./volumes/ssl:/etc/rabbitmq/ssl:ro
environment:
- RABBITMQ_ERLANG_COOKIE=${CLUSTER_COOKIE}
- RABBITMQ_DEFAULT_USER=${DEFAULT_USER}
- RABBITMQ_DEFAULT_PASS=${DEFAULT_PASSWORD}
volumes:
rabbitmq-data:
driver: local
Optional - Adding TLS For Prometheus Monitoring Connections
If you wish to add TLS to the AMQP connections, then you can simply add another configuration file like so:
editor ./volumes/configs/prometheus-tls.conf
prometheus.ssl.port = 15691
prometheus.ssl.cacertfile = /etc/rabbitmq/ssl/chain.pem
prometheus.ssl.certfile = /etc/rabbitmq/ssl/cert.pem
prometheus.ssl.keyfile = /etc/rabbitmq/ssl/privkey.pem
# Comment out the line below if you still wish to allow non-encrypted connections
prometheus.tcp.listener = none
# Uncomment the lines below if you wish to use TLS peer verification
# whereby the client connecting must provide a TLS certificate signed
# by your certificate authority.
#
#prometheus.ssl.verify = verify_peer
#prometheus.ssl.depth = 2
#prometheus.ssl.fail_if_no_peer_cert = true
Optional - Adding TLS For AMQP Connections
If you wish to add TLS to the AMQP connections, then you can simply add another configuration file like so:
editor ./volumes/configs/amqp-tls.conf
... and give it the following content
# Specify the AMQP TLS port
listeners.ssl.default = 5671
# Specify certificate file locations
ssl_options.cacertfile = /etc/rabbitmq/ssl/chain.pem
ssl_options.certfile = /etc/rabbitmq/ssl/cert.pem
ssl_options.keyfile = /etc/rabbitmq/ssl/privkey.pem
# Do not perform peer TLS verification
ssl_options.verify = verify_none
ssl_options.fail_if_no_peer_cert = false
Strict Client Checking
The configuration above allows non-TLS connections to still occur. If you wish to disable that, and force the server to verify the clients connecting to the server, then use the following configuration content instead.
# disables non-TLS listeners, only TLS-enabled clients will be able to connect
listeners.tcp = none
# Specify the TLS port
listeners.ssl.default = 5671
# Specify certificate file locations
ssl_options.cacertfile = /etc/rabbitmq/ssl/chain.pem
ssl_options.certfile = /etc/rabbitmq/ssl/cert.pem
ssl_options.keyfile = /etc/rabbitmq/ssl/privkey.pem
# Verify peer and fail if they do not have a valid certificate.
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = true
Hostname Is Important
You will see that we specify the hostname
in both the docker run commands and the docker compose files. This is because it is very important for the
data persistence as RabbitMQ uses the hostname as part of the folder name in the mnesia directory.
References
- Networking and RabbitMQ
- RabbitMQ Docs - Management Plugin - HTTPS
- RabbitMQ Docs - TLS Support
- RabbitMQ Docs - Securing Prometheus Scraping Endpoint with TLS
First published: 16th August 2018