How to Run RabbitMQ 4 with Docker and Docker Compose

Run RabbitMQ 4 with Docker Compose: pinned management image, healthcheck, persistent volume, rabbitmq.conf, quorum queues, Prometheus metrics and backups.

Running RabbitMQ 4 with Docker Compose is the quickest way to get a message broker for local development, CI, or a small single-node production setup. In this guide you will run the official rabbitmq:4.4.0-management image with a pinned tag, credentials in an .env file, a mounted rabbitmq.conf, a named volume for persistence, a healthcheck, quorum queues by default, and Prometheus metrics. You will also back the broker up and restore it.

Everything below was tested on Docker Engine 29 with RabbitMQ 4.4.0 (Erlang 29).

What changed in RabbitMQ 4

If you are coming from a 3.x setup, a few things matter for a Compose deployment:

  • Classic mirrored queues are gone. Use quorum queues for replicated, durable queues. This guide makes quorum the default queue type.
  • rabbitmqadmin v2 ships in the image. It is a new CLI with a different syntax from the old Python rabbitmqadmin.
  • Most RABBITMQ_* environment variables for configuration were removed from the image years ago. Put settings in rabbitmq.conf. Only the default user and password variables are still read, and only on first boot.

Prerequisites

Confirm Docker and Compose are available:

docker version --format '{{.Server.Version}}'
docker compose version

Step 1: Create the project directory

mkdir -p ~/rabbitmq && cd ~/rabbitmq

All the files below go in this directory.

Step 2: Store the credentials in an .env file

Create .env:

RABBITMQ_DEFAULT_USER=admin
RABBITMQ_DEFAULT_PASS=change-me-to-a-long-random-password

Lock it down and keep it out of Git:

chmod 600 .env
echo ".env" >> .gitignore

When RABBITMQ_DEFAULT_USER is set, RabbitMQ creates that user as an administrator and does not create the default guest user.

These variables are only applied when the data directory is empty, on the very first start. Changing them later does nothing. To change the password afterwards, use rabbitmqctl change_password (shown in Step 7).

Step 3: Write rabbitmq.conf

Create rabbitmq.conf:

# Listeners
listeners.tcp.default = 5672
management.tcp.port = 15672

# Keep the broker healthy on a small host
vm_memory_high_watermark.relative = 0.6
disk_free_limit.absolute = 2GB

# New queues in the default vhost are quorum queues unless the client asks otherwise
default_queue_type = quorum

log.console = true
log.console.level = info

What each setting does:

  • vm_memory_high_watermark.relative = 0.6: RabbitMQ blocks publishers when it uses 60% of the memory it can see. Set a memory limit on the container if the host runs other services.
  • disk_free_limit.absolute = 2GB: publishers are blocked when free disk drops below 2 GB, before the disk fills up completely.
  • default_queue_type = quorum: clients that declare a queue without x-queue-type get a durable, replicated quorum queue.

The file is mounted into /etc/rabbitmq/conf.d/, so it is loaded on top of the image’s own 10-defaults.conf instead of replacing it.

Step 4: Enable plugins

Create enabled_plugins (note the trailing full stop, it is an Erlang term):

[rabbitmq_management,rabbitmq_prometheus].
  • rabbitmq_management: the web UI and HTTP API on port 15672.
  • rabbitmq_prometheus: metrics on port 15692 at /metrics.

Step 5: Create the Compose file

Create compose.yaml:

services:
  rabbitmq:
    image: rabbitmq:4.4.0-management
    container_name: rabbitmq
    hostname: rabbitmq
    restart: unless-stopped
    env_file: .env
    ports:
      - "5672:5672"
      - "15672:15672"
      - "15692:15692"
    volumes:
      - rabbitmq_data:/var/lib/rabbitmq
      - ./rabbitmq.conf:/etc/rabbitmq/conf.d/20-custom.conf:ro
      - ./enabled_plugins:/etc/rabbitmq/enabled_plugins:ro
    healthcheck:
      test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 30s

volumes:
  rabbitmq_data:

Key points:

  • Pinned tag (4.4.0-management): latest or 4-management can move you to a new minor version on the next docker compose pull. Bump the tag on purpose, after reading the release notes.
  • hostname: rabbitmq: RabbitMQ stores its data under a directory named after the node (rabbit@<hostname>). Without a fixed hostname, every new container gets a random one and starts with an empty database, even though the volume is still attached.
  • Named volume rabbitmq_data: queues, messages, users and vhosts survive container recreation.
  • Healthcheck: rabbitmq-diagnostics -q ping succeeds once the node is running. Other services can wait for it with depends_on: { rabbitmq: { condition: service_healthy } }.

If the broker is only used by other containers in the same Compose project, drop the 5672 port mapping and connect over the Compose network as rabbitmq:5672. Do not expose 15672 to the internet; put it behind a VPN or a reverse proxy with authentication.

Step 6: Start RabbitMQ

docker compose up -d --wait

--wait returns once the healthcheck passes:

 Container rabbitmq Healthy

Check the version, plugins and that the config was applied:

docker exec rabbitmq rabbitmqctl version
docker exec rabbitmq rabbitmq-plugins list -E -q
docker exec rabbitmq rabbitmqctl -q list_vhosts name default_queue_type
4.4.0
[E*] rabbitmq_management 4.4.0
[E*] rabbitmq_prometheus 4.4.0
name	default_queue_type
/	quorum

Check that all listeners are reachable:

docker exec rabbitmq rabbitmq-diagnostics -q check_port_connectivity
Successfully connected to ports 5672, 15672, 15692, 25672 on node rabbit@rabbitmq (using node hostname resolution)

Open the management UI at http://<server-ip>:15672 and log in with the user and password from .env.

Step 7: Manage users and vhosts

Give each application its own vhost and user instead of sharing the admin account:

docker exec rabbitmq rabbitmqctl add_vhost orders
docker exec rabbitmq rabbitmqctl add_user orders_app 'another-long-random-password'
docker exec rabbitmq rabbitmqctl set_permissions -p orders orders_app ".*" ".*" ".*"

Change the admin password later with:

docker exec rabbitmq rabbitmqctl change_password admin 'new-long-random-password'

Then update .env so the file still matches, even though it is only read on first boot.

Note that default_queue_type in rabbitmq.conf only sets the default for the / vhost created on first boot. For new vhosts, pass it explicitly:

docker exec rabbitmq rabbitmqctl add_vhost billing --default-queue-type quorum

Step 8: Publish and consume a test message

The image includes rabbitmqadmin v2, which talks to the HTTP API. Declare a quorum queue, publish a message and read it back:

docker exec rabbitmq rabbitmqadmin -u admin -p 'your-password' declare queue --name orders --type quorum
docker exec rabbitmq rabbitmqadmin -u admin -p 'your-password' publish message --routing-key orders --payload 'hello from compose'
docker exec rabbitmq rabbitmqadmin -u admin -p 'your-password' get messages --queue orders --count 1

The last command prints the message:

│ payload_bytes │ redelivered │ exchange │ routing_key │ message_count │ properties │ payload            │ payload_encoding │
│ 18            │ false       │          │ orders      │ 0             │            │ hello from compose │ string           │

Applications connect with an AMQP URL such as:

amqp://orders_app:another-long-random-password@<server-ip>:5672/orders

Step 9: Scrape metrics with Prometheus

The Prometheus plugin serves metrics without authentication on port 15692:

curl -s http://localhost:15692/metrics | head

Add a scrape job to your Prometheus config:

scrape_configs:
  - job_name: rabbitmq
    static_configs:
      - targets: ["<server-ip>:15692"]

If you do not have Prometheus yet, see How to Run Prometheus with Docker and Docker Compose.

Step 10: Back up and restore RabbitMQ

There are two things to back up: definitions (users, vhosts, permissions, queues, exchanges, bindings, policies) and the data directory (the messages themselves).

Export and import definitions

Definitions are small JSON and can be exported while the broker runs:

docker exec rabbitmq rabbitmqctl -q export_definitions /tmp/definitions.json
docker cp rabbitmq:/tmp/definitions.json ./definitions-$(date +%F).json

Restore them into a running broker:

docker cp ./definitions-2026-11-09.json rabbitmq:/tmp/definitions.json
docker exec rabbitmq rabbitmqctl import_definitions /tmp/definitions.json

The export contains password hashes, so store it as carefully as .env.

Back up the data volume

To keep messages too, stop the broker and archive the volume. Compose prefixes the volume name with the project (directory) name, so check it first:

docker volume ls | grep rabbitmq_data

For a project directory named rabbitmq, the volume is rabbitmq_rabbitmq_data:

docker compose stop rabbitmq
docker run --rm -v rabbitmq_rabbitmq_data:/data -v "$PWD":/backup alpine \
  tar czf /backup/rabbitmq-data-$(date +%F).tar.gz -C /data .
docker compose start rabbitmq

To restore, stop the broker, empty the volume and extract the archive:

docker compose stop rabbitmq
docker run --rm -v rabbitmq_rabbitmq_data:/data -v "$PWD":/backup alpine \
  sh -c 'rm -rf /data/* /data/.[!.]* && tar xzf /backup/rabbitmq-data-2026-11-09.tar.gz -C /data'
docker compose start rabbitmq

The restored data only works with the same hostname (rabbitmq), because the files live under mnesia/rabbit@rabbitmq. For more on backup options, see How to Backup and Restore RabbitMQ Data and Configurations.

Step 11: Upgrade RabbitMQ

  1. Export definitions and back up the volume (Step 10).
  2. Read the release notes for the target version and check its supported upgrade path. The safe default is one minor series at a time (for example 4.3 to 4.4), with all feature flags enabled before each step.
  3. Change the tag in compose.yaml, then:
docker compose pull
docker compose up -d --wait
docker exec rabbitmq rabbitmqctl version

After the upgrade, enable any new feature flags:

docker exec rabbitmq rabbitmqctl enable_feature_flag all

Useful commands

docker compose logs -f rabbitmq                         # follow the broker log
docker exec rabbitmq rabbitmq-diagnostics status        # node status, memory, disk
docker exec rabbitmq rabbitmqctl list_queues name type messages consumers
docker exec rabbitmq rabbitmq-diagnostics check_alarms  # memory or disk alarms
docker compose down                                     # stop; the volume is kept
docker compose down -v                                  # stop and DELETE all data

Conclusion

You now have RabbitMQ 4.4 running with Docker Compose: a pinned image, credentials outside the Compose file, a mounted rabbitmq.conf, quorum queues by default, a healthcheck, persistent storage tied to a fixed hostname, Prometheus metrics, and a tested backup and restore. This setup is a single node. If you need high availability, run a three-node cluster with quorum queues spread across the nodes.

comments powered by Disqus
Citizix Ltd
Built with Hugo
Theme Stack designed by Jimmy