RabbitMQ — Local Setup & CLI¶
Images¶
| Image | Contains |
|---|---|
rabbitmq:4 |
Broker only |
rabbitmq:4-management |
Broker + management plugin (web UI and HTTP API on 15672) — the usual choice for local work and tests |
rabbitmq:4-management-alpine |
Same on Alpine, smaller |
Pin a full version (for example rabbitmq:4.3-management) in CI so an image update doesn't change behaviour under your tests.
Single Container¶
docker run -d --name rabbitmq \
--hostname rabbitmq \
-p 5672:5672 -p 15672:15672 \
-e RABBITMQ_DEFAULT_USER=app \
-e RABBITMQ_DEFAULT_PASS=app-secret \
rabbitmq:4-management
- Set
--hostnamewhen you keep data in a volume — the node name israbbit@<hostname>, and a new random container hostname means a new, empty node. guest/guestfrom other hosts: RabbitMQ allowsguestonly from localhost, but the official Docker image turns that off (loopback_users.guest = falsein/etc/rabbitmq/conf.d/10-defaults.conf), so in Dockerguestworks from the host and from other containers. On a package install or a custom config it getsACCESS_REFUSEDfrom anywhere but localhost — use your own user outside local runs.- With
RABBITMQ_DEFAULT_USERset, noguestuser is created. RABBITMQ_DEFAULT_VHOSTreplaces the default vhost: withRABBITMQ_DEFAULT_VHOST=ordersthe broker starts with onlyorders, no/.
Docker Compose with a Healthcheck¶
services:
rabbitmq:
image: rabbitmq:4-management
hostname: rabbitmq
ports:
- "5672:5672"
- "15672:15672"
environment:
RABBITMQ_DEFAULT_USER: app
RABBITMQ_DEFAULT_PASS: app-secret
volumes:
- rabbitmq-data:/var/lib/rabbitmq
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"]
interval: 5s
timeout: 5s
retries: 12
worker:
build: .
environment:
AMQP_URL: amqp://app:app-secret@rabbitmq:5672/
depends_on:
rabbitmq:
condition: service_healthy
volumes:
rabbitmq-data:
rabbitmq-diagnostics -q ping succeeds once the node is running. For a stricter check before tests start, use rabbitmq-diagnostics -q check_port_connectivity (listeners accept connections).
Connection URLs¶
amqp://user:password@host:5672/ # vhost "/"
amqp://user:password@host:5672/orders # vhost "orders"
amqp://user:password@host:5672/%2F # vhost "/" written explicitly (URL-encoded)
amqps://user:password@host:5671/ # TLS
rabbitmqctl and rabbitmq-diagnostics¶
Run inside the container: docker exec rabbitmq <command>.
Don't run the CLI in the first second after start
docker exec runs as root. If a CLI command runs before the broker has created /var/lib/rabbitmq/.erlang.cookie, the CLI creates it owned by root, and the broker, running as rabbitmq, fails with eacces on the cookie and exits. A script that does docker run and immediately loops on docker exec ... rabbitmq-diagnostics ping hits this. Wait for the healthcheck, or run the command as the broker user: docker exec -u rabbitmq rabbitmq rabbitmq-diagnostics -q ping.
| Task | Command |
|---|---|
| Node health | rabbitmq-diagnostics -q ping |
| Node status, versions, memory | rabbitmq-diagnostics status |
| Alarms (memory, disk) | rabbitmq-diagnostics alarms |
| Queues with depth | rabbitmqctl list_queues name type messages messages_ready messages_unacknowledged consumers |
| Queues in a vhost | rabbitmqctl list_queues -p orders name messages |
| Exchanges | rabbitmqctl list_exchanges name type |
| Bindings | rabbitmqctl list_bindings source_name routing_key destination_name |
| Connections and channels | rabbitmqctl list_connections user peer_host state · rabbitmqctl list_channels connection prefetch_count messages_unacknowledged |
| Consumers | rabbitmqctl list_consumers queue_name channel_pid prefetch_count |
| Empty a queue | rabbitmqctl purge_queue billing |
| Delete a queue | rabbitmqctl delete_queue billing |
| Create a vhost | rabbitmqctl add_vhost orders |
| Create a user | rabbitmqctl add_user billing 's3cret' |
| Grant permissions (configure, write, read) | rabbitmqctl set_permissions -p orders billing ".*" ".*" ".*" |
| Tag a user as admin for the UI | rabbitmqctl set_user_tags billing administrator |
| Enabled plugins | rabbitmq-plugins list -e |
| Enable a plugin (stream protocol on 5552) | rabbitmq-plugins enable rabbitmq_stream |
The -management image already enables rabbitmq_management and rabbitmq_prometheus (metrics on 15692).
messages_unacknowledged that keeps growing while messages_ready stays low usually means a consumer takes messages and never acks them.
Management UI and HTTP API¶
The UI at http://localhost:15672 shows queues with rates, lets you publish and get messages by hand, and exports definitions. The same data is available over the HTTP API, which is handy in tests and scripts:
curl -s -u app:app-secret http://localhost:15672/api/overview | jq '.rabbitmq_version'
curl -s -u app:app-secret http://localhost:15672/api/queues/%2F/billing | jq '{messages, consumers}'
curl -s -u app:app-secret http://localhost:15672/api/queues | jq '.[] | {name, messages}'
- The vhost goes into the path URL-encoded:
/is%2F. - Queue counters in the API are refreshed every few seconds (statistics interval 5 s by default; quorum queues can lag longer), not in real time — in tests poll with a deadline, don't read once.
- Getting messages through the UI or API with the default "Nack message requeue true" mode redelivers them; they come back with
redelivered=True.
Definitions: Topology as Code¶
Exchanges, queues, bindings, users, vhosts and policies can be exported and imported as one JSON file:
curl -s -u app:app-secret http://localhost:15672/api/definitions > definitions.json # export
docker exec rabbitmq rabbitmqctl import_definitions /tmp/definitions.json # import (file inside the container)
To load definitions at start, mount the file and point the broker at it in rabbitmq.conf:
# /etc/rabbitmq/rabbitmq.conf
load_definitions = /etc/rabbitmq/definitions.json
For tests it is usually simpler to declare the topology from the test fixtures (see 04 Testing) — declarations are idempotent when the properties match.
Policies¶
Policies apply queue settings by name pattern without changing the code that declares queues:
# every queue starting with "billing." gets a DLX and a length limit
rabbitmqctl set_policy billing-dlx "^billing\." \
'{"dead-letter-exchange":"billing.dlx","max-length":100000}' --apply-to queues
Arguments set by the client at declaration (x-...) take precedence over some policy keys and can't be changed afterwards; policies can. Prefer policies for operational limits (TTL, length, DLX) so they can be tuned without redeploying.
Checklist¶
- Image pinned to a version, with the management plugin for local and test use
-
hostnameset when data lives in a volume - Own user and vhost instead of
guest - Healthcheck with
rabbitmq-diagnostics -q ping, services wait on it - Topology declared from code or loaded from definitions, not clicked in the UI