How to add initial users when starting a RabbitMQ Docker container?

113.2k views Asked by At

Currently i am starting RabbitMQ Docker container using the default RabbitMQ image from DockerHub. Using the following commands.

docker run --restart=always \
-d \
-e RABBITMQ_NODENAME=rabbitmq \
-v /opt/docker/rabbitmq/data:/var/lib/rabbitmq/mnesia/rabbitmq \
-p 5672:5672 \
-p 15672:15672 \
--name rabbitmq rabbitmq:3-management

I have a need where i want to provide defaults users / and virtual-hosts when the image is first started. For example to create a default 'test-user'.

Currently i have to do that manually by using the management plugin and adding the users / virtual-hosts via the web ui. Is there a way i can provide default settings when starting the RabbitMQ image?

16

There are 16 answers

23
george.yord On BEST ANSWER

You can create a simple Dockerfile that extends the functionality of the basic image and creates a default user. The Docker file you need is the following:

FROM rabbitmq

# Define environment variables.
ENV RABBITMQ_USER user
ENV RABBITMQ_PASSWORD user
ENV RABBITMQ_PID_FILE /var/lib/rabbitmq/mnesia/rabbitmq

ADD init.sh /init.sh
RUN chmod +x /init.sh
EXPOSE 15672

# Define default command
CMD ["/init.sh"]

And the init.sh:

#!/bin/sh

# Create Rabbitmq user
( rabbitmqctl wait --timeout 60 $RABBITMQ_PID_FILE ; \
rabbitmqctl add_user $RABBITMQ_USER $RABBITMQ_PASSWORD 2>/dev/null ; \
rabbitmqctl set_user_tags $RABBITMQ_USER administrator ; \
rabbitmqctl set_permissions -p / $RABBITMQ_USER  ".*" ".*" ".*" ; \
echo "*** User '$RABBITMQ_USER' with password '$RABBITMQ_PASSWORD' completed. ***" ; \
echo "*** Log in the WebUI at port 15672 (example: http:/localhost:15672) ***") &

# $@ is used to pass arguments to the rabbitmq-server command.
# For example if you use it like this: docker run -d rabbitmq arg1 arg2,
# it will be as you run in the container rabbitmq-server arg1 arg2
rabbitmq-server $@

This script also initialize and expose the RabbitMQ webadmin at port 15672.

0
user2915097 On

Here is an example of how I add an unprivileged user gg RUN useradd -d /home/gg -m -s /bin/bash gg RUN echo gg:gg | chpasswd RUN echo 'gg ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers.d/gg RUN chmod 0440 /etc/sudoers.d/gg

0
Fiacc On

I had to make a few changes to the script in the accepted answer to get it working based on the comments above.

Dockerfile

FROM rabbitmq

# Define environment variables.
ENV RABBITMQ_USER user
ENV RABBITMQ_PASSWORD user

ADD init.sh /init.sh
EXPOSE 15672

# Define default command
CMD ["/init.sh"]

init.sh

#!/bin/sh
( sleep 10 && \
rabbitmqctl add_user $RABBITMQ_USER $RABBITMQ_PASSWORD && \
rabbitmqctl set_user_tags $RABBITMQ_USER administrator && \
rabbitmqctl set_permissions -p / $RABBITMQ_USER  ".*" ".*" ".*" ) & \
rabbitmq-server
0
Martin On

In my case sleep 5 solution above did not work because RabbitMQ startup time was much longer and not predictable. Posting solution which waits until RabbitMQ is up and running:

  • Dockerfile

    FROM rabbitmq:3-management
    ADD init.sh /
    ADD config_rabbit.sh /
    RUN chmod +x /init.sh /config_rabbit.sh
    ENTRYPOINT ["/init.sh"]
    
  • init.sh

    #!/bin/bash
    
    # Launch config script in background
    # Note there is no RabbitMQ Docker image support for executing commands after server (PID 1) is running (something like "ADD schema.sql /docker-entrypoint-initdb.d" in MySql image), so we are using this trick
    /config_rabbit.sh &
    
    # Launch
    /docker-entrypoint.sh rabbitmq-server
    
  • config_rabbit.sh

    #!/bin/bash
    
    # This script needs to be executed just once
    if [ -f /$0.completed ] ; then
      echo "$0 `date` /$0.completed found, skipping run"
      exit 0
    fi
    
    # Wait for RabbitMQ startup
    for (( ; ; )) ; do
      sleep 5
      rabbitmqctl -q node_health_check > /dev/null 2>&1
      if [ $? -eq 0 ] ; then
        echo "$0 `date` rabbitmq is now running"
        break
      else
        echo "$0 `date` waiting for rabbitmq startup"
      fi
    done
    
    # Execute RabbitMQ config commands here
    
    # Create user
    rabbitmqctl add_user USER PASSWORD
    rabbitmqctl set_permissions -p / USER ".*" ".*" ".*"
    echo "$0 `date` user USER created"
    
    # Create queue
    rabbitmqadmin declare queue name=QUEUE durable=true
    echo "$0 `date` queues created"
    
    # Create mark so script is not ran again
    touch /$0.completed
    
2
AngryUbuntuNerd On

The newest version of the RabbitMQ image on Dockerhub has in-built functionality for changing the default username / password from "guest" / "guest" to something else.

Simply set the environment variables "RABBITMQ_DEFAULT_USER" and "RABBITMQ_DEFAULT_PASS" when starting the image.

As a docker command, you would run the image like this:

docker run \
-e RABBITMQ_DEFAULT_USER=test-user \
-e RABBITMQ_DEFAULT_PASS=test-user \
-p 5672:5672 \
rabbitmq
0
angelcool.net On

Using cron on a customized image via Dockerfile instructions worked for me:

# add rabbitmq user with /usr/sbin/rabbitmqctl at boot time.
RUN  echo "@reboot  root  sleep 5 && rabbitmqctl add_user admin admin && rabbitmqctl set_user_tags admin administrator && rabbitmqctl set_permissions -p / admin \".*\" \".*\" \".*\"" >> /etc/crontab

The image is based on Rocky Linux and Systemd. Here's my full Dockerfile:

FROM rockylinux/rockylinux:latest
LABEL maintainer="[email protected]"

# remove unecessary systemd unit files
ENV container docker
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \
systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;

# import rabbitmq repo signatures
RUN rpm --import https://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc && \
rpm --import 'https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/gpg.E495BB49CC4BBE5B.key' && \
rpm --import 'https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-server/gpg.9F4587F226208342.key'

# copy rabbitmq repo config
COPY config/rabbitmq.repo /etc/yum.repos.d/rabbitmq.repo

# install packages
RUN dnf -y update \
&& dnf -y install epel-release.noarch \
http://rpms.remirepo.net/enterprise/remi-release-8.rpm \
&& dnf module -y install php:remi-8.0 \
&& dnf -y install rabbitmq-server \
supervisor \
memcached \
iproute \
# postfix \
mailx \
vim \
nano \
dos2unix \
wget \
openssh \
rsync \
unzip \
ImageMagick \
ncurses \
cronie \
&& dnf clean all

# create admin user account
ARG UID=1000
RUN useradd --create-home --uid $UID admin

# enable services
RUN systemctl enable rabbitmq-server.service memcached.service \
&& rabbitmq-plugins enable rabbitmq_management

# add rabbitmq user with /usr/sbin/rabbitmqctl at boot time.
RUN  echo "@reboot  root  sleep 5 && rabbitmqctl add_user admin admin && rabbitmqctl set_user_tags admin administrator && rabbitmqctl set_permissions -p / admin \".*\" \".*\" \".*\"" >> /etc/crontab

EXPOSE 15672 9001
ENTRYPOINT ["/sbin/init"]

Build the image:

docker build --build-arg UID=$(id -u) -t customRockyLinux:customRockyLinux .

Run the image:

docker run  --name customRL_container -d --privileged -p 15672:15672 -p 9001:9001 customRockyLinux:customRockyLinux

Interact with the container as root :

docker exec -it customRL_container bash

Or as specific user:

docker exec -it --user admin customRL_container bash

Verify RabbitMQ users:

root@a2dc7498de45 /]# rabbitmqctl list_users
user    tags
admin   [administrator]
guest   [administrator]
[root@a2dc7498de45 /]#
[root@a2dc7498de45 /]#
[root@a2dc7498de45 /]# rabbitmqctl --version
3.9.5
[root@a2dc7498de45 /]# cat /etc/redhat-release 
Rocky Linux release 8.4 (Green Obsidian)

Good luck!!

0
Alfred Huang On

In my case, I wonder if I can dump the docker container user/vhost/data by simply mounting the data folder.

I found the following documentation: https://www.rabbitmq.com/backup.html, which helps too much.


For now, I do mount the /var/lib/rabbitmq volume to the host, but when the container is recreated, the configurations of user and vhosts gone away.

Soom I realized that after a recreation of the container, a new dataset is generated, with a different id.

So the old data is still there, but the id is disconnected.

In my example, the 0df72ae1a7a5 one is old, when I create a new one 268bac197c69, the old data is not active any more.

root@268bac197c69:~/mnesia# ls -alh /var/lib/rabbitmq/mnesia
total 100K
drwxr-xr-x. 14 rabbitmq rabbitmq 4.0K Jun 13 13:43 .
drwxr-xr-x.  5 rabbitmq root     4.0K Jun 13 13:42 ..
drwxr-xr-x.  4 rabbitmq rabbitmq 4.0K Mar  6  2020 rabbit@0df72ae1a7a5
-rw-r--r--.  1 rabbitmq rabbitmq   64 Mar  6  2020 rabbit@0df72ae1a7a5-feature_flags
drwxr-xr-x.  2 rabbitmq rabbitmq 4.0K Mar  6  2020 rabbit@0df72ae1a7a5-plugins-expand
-rw-r--r--.  1 rabbitmq rabbitmq    2 Mar  6  2020 [email protected]
drwxr-xr-x.  4 rabbitmq rabbitmq 4.0K Jun 13 13:43 rabbit@268bac197c69
-rw-r--r--.  1 rabbitmq rabbitmq  148 Jun 13 13:43 rabbit@268bac197c69-feature_flags
drwxr-xr-x. 10 rabbitmq rabbitmq 4.0K Jun 13 13:43 rabbit@268bac197c69-plugins-expand
-rw-r--r--.  1 rabbitmq rabbitmq    3 Jun 13 13:43 [email protected]

In the container, the following command shows the current active id:

rabbitmqctl eval 'rabbit_mnesia:dir().'

It prints "/var/lib/rabbitmq/mnesia/rabbit@268bac197c69", the current newly created one.

So now the problem is now reduced to:

How to restore the old data with the specific old id when the container recreates?

Soon, I found the current id is the same with the container hostname, which is randomly generated when the container created!

So how the stick the id with a specific value? I check the docker-hub rabbitmq page: https://hub.docker.com/_/rabbitmq

One of the important things to note about RabbitMQ is that it stores data based on what it calls the "Node Name", which defaults to the hostname. What this means for usage in Docker is that we should specify -h/--hostname explicitly for each daemon so that we don't get a random hostname and can keep track of our data:

So comes the final solution, we just need to specify the hostname to a specific value, everything will come back automatically when the container recreates.


Final Solution:

Just add the hostname setting in our docker-compose section:

Notice: The hostname line and volumes line matters.

  rabbitmq:
    image: rabbitmq:management
    container_name: rabbitmq
    restart: always
    hostname: 0df72ae1a7a5
    environment:
     RABBITMQ_DEFAULT_USER: rabbit
     RABBITMQ_DEFAULT_PASS: rabbit
    volumes:
     - /var/docker/rabbitmq/var/lib/rabbitmq:/var/lib/rabbitmq
7
sudo On

Came up with a solution that suits my needs, leaving it here in case anybody else needs it.

Summary

The idea is to take a standard rabbitmq container with management plugin enabled and use it to create the required configuration, then export and use it to start new containers. The below solution creates a derived docker image but it also works to just mount the two files at runtime (e.g. using docker compose).

References

Components

  • official rabbitmq image, management plugin version (rabbitmq:management)

  • custom image based on the original one, with this Dockerfile (using version 3.6.6):

     FROM rabbitmq:3.6.6-management
     ADD rabbitmq.config /etc/rabbitmq/
     ADD definitions.json /etc/rabbitmq/
     RUN chown rabbitmq:rabbitmq /etc/rabbitmq/rabbitmq.config /etc/rabbitmq/definitions.json
     CMD ["rabbitmq-server"]
    
  • rabbitmq.config just tells rabbitmq to load definitions from the json file

  • definitions.json contains the users, vhosts, etc. and can be generated by the export function of the management web interface

rabbitmq.config example:

[
  {rabbit, [
    {loopback_users, []}
  ]},
  {rabbitmq_management, [
    {load_definitions, "/etc/rabbitmq/definitions.json"}
  ]}
].

definitions.json example:

{
 "rabbit_version": "3.6.6",
 "users": [
  {
   "name": "user1",
   "password_hash": "pass1",
   "hashing_algorithm": "rabbit_password_hashing_sha256",
   "tags": ""
  },
  {
   "name": "adminuser",
   "password_hash": "adminpass",
   "hashing_algorithm": "rabbit_password_hashing_sha256",
   "tags": "administrator"
  }
 ],
 "vhosts": [
  {
   "name": "\/vhost1"
  },
  {
   "name": "\/vhost2"
  }
 ],
 "permissions": [
  {
   "user": "user1",
   "vhost": "\/vhost1",
   "configure": ".*",
   "write": ".*",
   "read": ".*"
  }
 ],
 "parameters": [],
 "policies": [],
 "queues": [],
 "exchanges": [],
 "bindings": []
}

Alternave version

Deriving a new docker image is just one solution and works best when portability is key, since it avoids including host-based file management in the picture.

In some situations using the official image and providing configuration files from storage local to the host might be preferred.

The rabbitmq.config and definitions.json files are produced the same way, then mounted at runtime.

Notes:

  • I'm assuming they have been placed in /etc/so/ for the sake of these examples
  • files need to either be world readable or owned by the rabbitmq user or group (numerical id inside the docker container is 999), this needs to be handled by the host's sysadmin

docker run example:

    docker run --rm -it \
        -v /etc/so/rabbitmq.config:/etc/rabbitmq/rabbitmq.config:ro \
        -v /etc/so/definitions.json:/etc/rabbitmq/definitions.json:ro \
        rabbitmq:3.6-management

docker compose example:

    version: '2.1'
    services:
        rabbitmq:
            image: "rabbitmq:3.6-management"
            ports:
                - 5672:5672
                - 15672:15672
            volumes:
                - /etc/so/rabbitmq.config:/etc/rabbitmq/rabbitmq.config:ro
                - /etc/so/definitions.json:/etc/rabbitmq/definitions.json:ro
1
Dávid Molnár On

The above mentioned solutions have one caveat: they will "disable" the docker-entrypoint.sh script present in the official rabbit docker images. This may or may not be a problem for you. This script creates the initial RabbitMQ configuration file; adds some good default values (e.g. total memory limit if the container is running with a memory limit).

If you want to keep full compatibility and you don't want to "disable" this script you can use the following approach. It'll add an additional admin user with admin password and also keep guest user untouched. This can be useful for development.

This approach is using a definitions.json file to initialize the users using the management plugin. To inform the plugin about the definitions.json file we use the RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS environment variable (not the rabbitmq.conf file).

Create definitions.json file:

{
  "users": [
    {
      "name": "guest",
      "password_hash": "R184F4Fs6JLdo8tFqRjWnkJL2DlAZJupxEqkO/8kfV/G63+z",
      "hashing_algorithm": "rabbit_password_hashing_sha256",
      "tags": "administrator"
    },
    {
      "name": "admin",
      "password_hash": "FGA5ZeTOLHnIp4ZjxIj0PsShW/DpLgdYAlHsbli7KMMa8Z0O",
      "hashing_algorithm": "rabbit_password_hashing_sha256",
      "tags": "administrator"
    }
  ],
  "vhosts": [
    {
      "name": "/"
    }
  ],
  "permissions": [
    {
      "user": "guest",
      "vhost": "/",
      "configure": ".*",
      "write": ".*",
      "read": ".*"
    },
    {
      "user": "admin",
      "vhost": "/",
      "configure": ".*",
      "write": ".*",
      "read": ".*"
    }
  ],
  "parameters": [],
  "policies": [],
  "queues": [],
  "exchanges": [],
  "bindings": []
}

Create custom Dockerfile:

FROM rabbitmq:3.8.3-management

ADD --chown=rabbitmq ./definitions.json /etc/rabbitmq/

ENV RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="-rabbitmq_management load_definitions \"/etc/rabbitmq/definitions.json\""

Use the following command to build the image: docker build --tag myrabbit:1.0.0 .

Then run it: docker run -d -p 5672:5672 -p 15672:15672 --restart unless-stopped --name rabbitmq myrabbit:1.0.0

0
scarba05 On

Some of the other solutions here weren't working with TLS because they disable the parent entrypoint. The others have unnecessary steps as there is an undocumented feature of the parent image that it will consume a definitions.json if it is present under /etc/rabbitmq.

This seems like the simplest approach:

Dockerfile

FROM rabbitmq:3.8.2-management
ADD definitions.json /etc/rabbitmq/
RUN chown rabbitmq:rabbitmq /etc/rabbitmq/definitions.json

definitions.json - edit to meet you users / vhosts / permissions needs

{
"users": [
    {
    "name": "guest",
    "password_hash": "R184F4Fs6JLdo8tFqRjWnkJL2DlAZJupxEqkO/8kfV/G63+z",
    "hashing_algorithm": "rabbit_password_hashing_sha256",
    "tags": "administrator"
    },
    {
    "name": "admin",
    "password_hash": "FGA5ZeTOLHnIp4ZjxIj0PsShW/DpLgdYAlHsbli7KMMa8Z0O",
    "hashing_algorithm": "rabbit_password_hashing_sha256",
    "tags": "administrator"
    }
],
"vhosts": [
    {
    "name": "/"
    }
],
"permissions": [
    {
    "user": "guest",
    "vhost": "/",
    "configure": ".*",
    "write": ".*",
    "read": ".*"
    },
    {
    "user": "admin",
    "vhost": "/",
    "configure": ".*",
    "write": ".*",
    "read": ".*"
    }
],
"parameters": [],
"policies": [],
"queues": [],
"exchanges": [],
"bindings": []
}
0
garuda one On

Well...it will probably be obvious by now since the image and docs have been updated, but because I searched my way here anyway, there are environment variables for at least a default user and vhost (but not multiple, yet):

If you wish to change the default username and password of guest / guest, you can do so with the RABBITMQ_DEFAULT_USER and RABBITMQ_DEFAULT_PASS environmental variables. These variables were available previously in the docker-specific entrypoint shell script but are now available in RabbitMQ directly.

$ docker run -d --hostname my-rabbit --name some-rabbit -e
RABBITMQ_DEFAULT_USER=user -e RABBITMQ_DEFAULT_PASS=password
rabbitmq:3-management

If you wish to change the default vhost, you can do so with the RABBITMQ_DEFAULT_VHOST environmental variables:

$ docker run -d --hostname my-rabbit --name some-rabbit -e
RABBITMQ_DEFAULT_VHOST=my_vhost rabbitmq:3-management

But craftsmannadeem's answer using definitions is the right answer: create a definitions.json and import it via the load_definitions config key.

1
Cyborg On

Currently i have to do that manually by using the management plugin and adding the users / virtual-hosts via the web ui. Is there a way i can provide default settings when starting the RabbitMQ image?

In my case, i'm using a rabbitmq container for my local development. I am using the rabbitmq:3.12.4-management-alpine image.

Since RabbitMQ changed the way they are writing the file rabbitmq.config (now renamed rabbitmq.conf), the solution here do not works anymore for me.

Basically, i'm doing the same thing but through a docker-compose file:

Here is how i'm describing my broker service:

version: "3.7"

networks:
    default:
        driver: bridge

services:
    broker-service-rabbitmq:
        image: rabbitmq:3.12.4-management-alpine
        container_name: broker-test_rabbitmq-server
        restart: unless-stopped
        volumes:
            - ${PWD}/dev-resources/volumes/rabbitmq/advanced.config:/etc/rabbitmq/advanced.config:ro
            - ${PWD}/dev-resources/volumes/rabbitmq/definitions.json:/etc/rabbitmq/definitions.json:ro
        ports:
            - "${BROKER_UI_PORT:-8083}:15672"
        networks:
            - default
        healthcheck:
            test: [ "CMD", "rabbitmqctl", "node_health_check" ]
            interval: 15s
            timeout: 5s
            retries: 5
            start_period: 30s

Has you can see, i'm using a file called advanced.config wich is now the only way to use an erlang styled config file as described here.

[
  {rabbit, [
    {loopback_users, []}
  ]},
  {rabbitmq_management, [
    {load_definitions, "/etc/rabbitmq/definitions.json"}
  ]}
].

And here is the definitions.json file wich i've extracted from the web UI of RabbitMQ (the password for the admin account here is "admin" and the password for the service-test account is "P455w0rd") :

{
    "rabbit_version": "3.12.4",
    "rabbitmq_version": "3.12.4",
    "product_name": "RabbitMQ",
    "product_version": "3.12.4",
    "users": [
        {
            "name": "admin",
            "password_hash": "FT36tPaTkj3IXlMTg6MhTrz86evp4hdt2p60IxaJnmRWy7Ry",
            "hashing_algorithm": "rabbit_password_hashing_sha256",
            "tags": [
                "administrator"
            ],
            "limits": {}
        },
        {
            "name": "service-test",
            "password_hash": "36VESrI5GlnMSum5o6ytxm58GbCd05zlJmcdTNIVehmrX2Cs",
            "hashing_algorithm": "rabbit_password_hashing_sha256",
            "tags": [
                "None"
            ],
            "limits": {}
        }
    ],
    "vhosts": [
        {
            "name": "service-test"
        },
        {
            "name": "/"
        }
    ],
    "permissions": [
        {
            "user": "admin",
            "vhost": "service-test",
            "configure": ".*",
            "write": ".*",
            "read": ".*"
        },
        {
            "user": "service-test",
            "vhost": "service-test",
            "configure": ".*",
            "write": ".*",
            "read": ".*"
        },
        {
            "user": "admin",
            "vhost": "/",
            "configure": ".*",
            "write": ".*",
            "read": ".*"
        }
    ],
    "topic_permissions": [],
    "parameters": [],
    "global_parameters": [
        {
            "name": "cluster_name",
            "value": "rabbitmq-dev-service"
        },
        {
            "name": "internal_cluster_id",
            "value": "rabbitmq-cluster-id-oIZB0WpqtbIh5aYiNw_PDw"
        }
    ],
    "policies": [],
    "exchanges": [],
    "bindings": []
}
0
craftsmannadeem On

Create Two folders, data and etc

enter image description here

enabled_plugins

[rabbitmq_management,rabbitmq_prometheus].

rabbitmq.conf

    auth_mechanisms.1 = PLAIN
    auth_mechanisms.2 = AMQPLAIN
    loopback_users.guest = false
    listeners.tcp.default = 5672
    #default_pass = admin
    #default_user = admin
    hipe_compile = false
    #management.listener.port = 15672
    #management.listener.ssl = false
    management.tcp.port = 15672
    management.load_definitions = /etc/rabbitmq/definitions.json

definitions.json You can add as many users, queues, exchanges as you wish

  {
    "users": [
        {
        "name": "admin",
        "password": "admin",
        "tags": "administrator"
        }
    ],
    "vhosts": [
        {
        "name": "/"
        }
    ],
    "policies": [
        {
        "vhost": "/",
        "name": "ha",
        "pattern": "",
        "apply-to": "all",
        "definition": {
            "ha-mode": "all",
            "ha-sync-batch-size": 256,
            "ha-sync-mode": "automatic"
        },
        "priority": 0
        }
    ],
    "permissions": [
        {
        "user": "admin",
        "vhost": "/",
        "configure": ".*",
        "write": ".*",
        "read": ".*"
        }
    ],
    "queues": [
        {
        "name": "job-import.triggered.queue",
        "vhost": "/",
        "durable": true,
        "auto_delete": false,
        "arguments": {}
        }
    ],
    "exchanges": [
        {
        "name": "lob-proj-dx",
        "vhost": "/",
        "type": "direct",
        "durable": true,
        "auto_delete": false,
        "internal": false,
        "arguments": {}
        }
    ],
    "bindings": [
        {
        "source": "lob-proj-dx",
        "vhost": "/",
        "destination": "job-import.triggered.queue",
        "destination_type": "queue",
        "routing_key": "job-import.event.triggered",
        "arguments": {}
        }
    ]
  }

Run Rabbit

docker run --restart=always -d -p 5672:5672 -p 15672:15672 --mount type=bind,source=E:\docker\rabbit\data,target=/var/lib/rabbitmq/ --mount type=bind,source=E:\docker\rabbit\etc,target=/etc/rabbitmq/ --name rabbitmq --hostname my-rabbit rabbitmq:3.7.28-management

enter image description here

Taken from here

This approach does not require creating custom docker image, does not require docker-compose plus it persists state across restarts

5
Tom P. On

I would like to add that sudo's response helped me a lot. But that it still missed a command to be added to the Dockerfile.

The rabbitmq.config and definitions.json file should be owned by the rabbitmq user & group. So after adding the files run chown.

The full Dockerfile in my case was the following:

FROM rabbitmq:3-management-alpine
ADD definitions.json /etc/rabbitmq/
ADD rabbitmq.config /etc/rabbitmq/
RUN chown rabbitmq:rabbitmq /etc/rabbitmq/rabbitmq.config /etc/rabbitmq/definitions.json

EXPOSE 4369 5671 5672 15671 15672 25672

CMD ["rabbitmq-server"]

The rabbitmq.config file has the following content being a merge from the default image's config and the added definitions loading:

[
    { rabbit, [
        {loopback_users, []},
        { tcp_listeners, [ 5672 ]},
        { ssl_listeners, [ ]},
        { hipe_compile, false } 
    ]},
    { rabbitmq_management, [
        { load_definitions, "/etc/rabbitmq/definitions.json"},
        { listeners, [
            { port, 15672 },
            { ssl, false } 

        ]}
    ]}
].

The definitions file can be exported from the management interface in the overview tab.

So you would first create a normal 'empty' rabbitmq container. Define whatever users, exchanges and queues you like. Then enter the management interface, export the definitions and create your own image using the file as described above.

Downloading the definitions is the easiest way to get the right password hashes in the definitions file for your own passwords. If you do not wish to do that you should follow the instructions as noted here (https://www.rabbitmq.com/passwords.html) to generate the correct hashes.

1
Chris Berry On

In Kubernetes, similar to @sudo's answer; it is possible to load the definitions.json file into the container via a ConfigMap & Volume.

The ConfigMap rabbitmq-definitions-configmap is defined as a configmap created from a file, with the target being the definitions.json.

You can do the same thing for the rabbitmq.config file also.

Please take note of the usage of mountPath & subPath, just using mountPath did not work for me.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: rabbitmq-deployment
spec:
  selector:
    matchLabels:
      app: rabbitmq-deployment
  replicas: 1
  template:
    metadata:
      labels:
        app: rabbitmq-deployment
    spec:
      volumes:
      - name: rabbitmq-definitions
        configMap:
          name: rabbitmq-definitions-configmap
      containers:
      - name: rabbitmq
        image: rabbitmq:3.7.18-management-alpine
        imagePullPolicy: IfNotPresent
        envFrom:
        - configMapRef:
            name: rabbitmq-configmap
        - secretRef:
            name: rabbitmq-secrets
        volumeMounts:
        - name: rabbitmq-definitions
          mountPath: /etc/rabbitmq/definitions.json
          subPath: rabbitmq-definitions
0
0909EM On

With RabbitMQ 3.7, and the newer rabbitmq.conf (sysctl) configuration format, the following sets up RabbitMQ with a default user and queue in Docker, you can optionally add the following RUN commands in the dockerfile to create users...

RUN rabbitmqctl add_user {username} {password}
RUN rabbitmqctl set_user_tags {username} administrator
RUN rabbitmqctl set_permissions ...

rabbitmq.conf

# Default user
default_user = testuser
default_pass = testpassword

## The default "guest" user is only permitted to access the server
## via a loopback interface (e.g. localhost).
loopback_users.guest = true

# IPv4
listeners.tcp.default = 5672

## HTTP listener and embedded Web server settings.
management.tcp.port = 15672

# Load queue definitions
management.load_definitions = /etc/rabbitmq/definitions.json

#Ignore SSL
ssl_options.verify               = verify_peer
ssl_options.fail_if_no_peer_cert = true

definitions.json

{
  "rabbit_version": "3.7.11",
  "users": [
    {
      "name": "testuser",
      "password_hash": "txn+nsYVkAaIMvDsH8Fsyb3RWMCMWihRUVCk/wICL1NBKKvz",
      "hashing_algorithm": "rabbit_password_hashing_sha256",
      "tags": "administrator"
    }
  ],
  "vhosts": [ { "name": "test-vhost" } ],
  "permissions": [
    {
      "user": "testuser",
      "vhost": "test-vhost",
      "configure": ".*",
      "write": ".*",
      "read": ".*"
    }
  ],
  "topic_permissions": [],
  "parameters": [],
  "global_parameters": [
    {
      "name": "cluster_name",
      "value": "rabbit@test-rabbit"
    }
  ],
  "policies": [],
  "queues": [
    {
      "name": "testqueue",
      "vhost": "test-vhost",
      "durable": true,
      "auto_delete": false,
      "arguments": {}
    }
  ],
  "exchanges": [],
  "bindings": []
}

Dockerfile

FROM rabbitmq:3.7-management

COPY rabbitmq.conf /etc/rabbitmq
COPY definitions.json /etc/rabbitmq

RUN ls /etc/rabbitmq
RUN cat /etc/rabbitmq/rabbitmq.conf

Dockers commands to build and run the container...

docker build -t rabbitmq-with-queue .
docker run --rm -it --hostname my-rabbit -p 5672:5672 -p 15672:15672 rabbitmq-with-queue