Skip to content

RabbitMQ Docker Setup Guide

Overview

This guide covers how to set up RabbitMQ in its own Docker container and connect a development container to it for use with the MQSS messaging stack.


Prerequisites

  • Docker installed and running
  • Docker Compose (optional)

1. Setting Up the RabbitMQ Container

Option A (Tested) — Docker CLI

docker run -d \
  --name rabbitmq \
  --hostname rabbitmq \
  -p 5672:5672 \
  -p 15672:15672 \
  rabbitmq:3-management
Port Purpose
5672 AMQP protocol (messaging)
15672 Management UI (HTTP)

Important: Always use port 5672 for your application connections. Port 15672 is HTTP only — connecting your AMQP client to it will cause an immediate "connection closed unexpectedly" error.

Option B — Docker Compose

Create a docker-compose.yml at the root of your project:

services:
  rabbitmq:
    image: rabbitmq:3-management
    container_name: rabbitmq
    hostname: rabbitmq
    ports:
      - "5672:5672"
      - "15672:15672"
    environment:
      RABBITMQ_DEFAULT_USER: myuser
      RABBITMQ_DEFAULT_PASS: mypassword
      RABBITMQ_LOOPBACK_USERS: none
    networks:
      - mqss-net

  dev:
    build: .
    container_name: mqss-dev
    depends_on:
      - rabbitmq
    networks:
      - mqss-net

networks:
  mqss-net:
    driver: bridge

Start both containers:

docker compose up -d

2. Creating a Dedicated RabbitMQ User

By default, RabbitMQ restricts the guest user to localhost connections only. Since your dev container connects from a different container, create a dedicated user:

docker exec -it rabbitmq bash

rabbitmqctl add_user myuser mypassword
rabbitmqctl set_user_tags myuser administrator
rabbitmqctl set_permissions -p / myuser ".*" ".*" ".*"

Alternatively, pass credentials via environment variables in docker-compose.yml (see Option B above):

environment:
  RABBITMQ_DEFAULT_USER: myuser
  RABBITMQ_DEFAULT_PASS: mypassword
  RABBITMQ_LOOPBACK_USERS: none

3. Connecting the Dev Container to RabbitMQ

Networking

Both containers must be on the same Docker network. If using Docker Compose, this is handled automatically via the shared mqss-net network. If using Docker CLI:

# Create a shared network
docker network create mqss-net

# Connect both containers to it
docker network connect mqss-net rabbitmq
docker network connect mqss-net mqss-dev

Once on the same network, use the container name as the hostname:

mqss::TransportOptions<mqss::RabbitMqSimple> opts;
opts.host     = "rabbitmq";    // container name; use "localhost" for local installs
opts.port     = 5672;
opts.username = "myuser";
opts.password = "mypassword";

Passing Connection Details (Currently within header files)

The important AMPQ variables have been defined in:

QRM/include/ConnectionHandler.hpp

You can modify these as per your requirements.
Then in your C++ code:

mqss::TransportOptions<mqss::RabbitMqSimple> opts;
opts.host     = AMQP_SERVER;    // "rabbitmq" (container name); use "localhost" for local installs
opts.port     = AMQP_PORT;      // 5672
opts.username = AMQP_USER;      // "myuser"
opts.password = AMQP_PASSWORD;  // "mypassword"
opts.vhost    = AMQP_VHOST;     // "/"

4. Verifying the Connection

Check the Management UI

Open http://localhost:15672 in your browser and log in with your credentials. You should see:

  • Connections tab: active connections from your dev container
  • Queues tab: queues created by your executables

Check from the Terminal

# Verify the AMQP port is reachable from the dev container
nc -zv rabbitmq 5672

# List active connections
docker exec -it rabbitmq rabbitmqctl list_connections

# List queues
docker exec -it rabbitmq rabbitmqadmin list queues

5. Avoiding Common Pitfalls

Stale Consumers

If you kill your executables without clean shutdown, RabbitMQ may retain stale consumers on queues. This can cause multiple consumers competing for the same messages. To clear stale state:

# Close all connections
docker exec -it rabbitmq rabbitmqctl close_all_connections "clearing stale connections"

# Delete queues (they will be recreated on next run)
docker exec -it rabbitmq rabbitmqadmin delete queue name=compiler.tasks.queue
docker exec -it rabbitmq rabbitmqadmin delete queue name=scheduler.tasks.queue
docker exec -it rabbitmq rabbitmqadmin delete queue name=test.results.queue

Or simply restart the container to reset everything:

docker restart rabbitmq

Isolating Dev Queues

If multiple MQSS deployments share the same broker, prefix your queue names to avoid cross-contamination:

const std::string compiler_queue = "compiler.tasks.queue";
const std::string scheduler_queue = "scheduler.tasks.queue";
const std::string results_queue = "test.results.queue";

Note: Currently these queues are set within the root CMakeLists.txt i.e. QRM/CMakeLists.txt.

Clean Shutdown of Executables

Ensure executables close their RabbitMQ connections cleanly on exit by handling signals:

std::signal(SIGINT, [](int) {
    Logger::cleanup();
    exit(0);
});

std::signal(SIGTERM, [](int) {
    Logger::cleanup();
    exit(0);
});

And in your start.sh launch script, use SIGTERM with wait to allow clean shutdown:

trap "kill -SIGTERM $SCHEDULER_PID $COMPILER_PID $TEST_PID; wait; echo 'Stopped.'" SIGINT SIGTERM

6. Quick Reference

Task Command
Start RabbitMQ container docker compose up -d
Stop RabbitMQ container docker compose down
Open management UI http://localhost:15672
List queues docker exec -it rabbitmq rabbitmqadmin list queues
List consumers docker exec -it rabbitmq rabbitmqadmin list consumers
Clear stale connections docker exec -it rabbitmq rabbitmqctl close_all_connections "stale"
Delete a queue docker exec -it rabbitmq rabbitmqadmin delete queue name=<queue_name>
Restart broker docker restart rabbitmq