如何在启动RabbitMQ Docker容器时添加初始用户?

时间:2015-06-10 05:03:37

标签: docker rabbitmq

目前我正在使用来自DockerHub的默认RabbitMQ图像启动RabbitMQ Docker容器。使用以下命令。

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

我需要在首次启动图像时提供默认用户/和虚拟主机。例如,要创建默认的“测试用户”。

目前我必须通过使用管理插件并通过web ui添加用户/虚拟主机来手动执行此操作。有没有办法在启动RabbitMQ图像时提供默认设置?

13 个答案:

答案 0 :(得分:45)

提出了一个适合我需求的解决方案,将其留在这里,万一其他人需要它。

摘要

我们的想法是采用一个标准的rabbitmq容器,启用管理插件,然后使用它创建所需的配置,然后导出并使用它来启动新的容器。下面的解决方案创建了一个派生的docker镜像,但它也可以在运行时挂载这两个文件(例如使用docker compose)。

参考

部件

  • 官方rabbitmq图片,管理插件版本( rabbitmq:management
  • 基于原始图像的自定义图像,使用此Dockerfile(使用版本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 告诉rabbitmq从json文件加载定义
  • definitions.json 包含用户,虚拟主机等,可以通过管理Web界面的导出功能生成

rabbitmq.config 示例:

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

definitions.json 示例:

{
 "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版本

获取新的docker镜像只是一种解决方案,在可移植性至关重要时效果最佳,因为它避免了在图片中包含基于主机的文件管理。

在某些情况下,使用官方映像并从主机本地存储提供配置文件可能是首选。

rabbitmq.config和definitions.json文件以相同的方式生成,然后在运行时挂载

注意:

  • 我假设为了这些例子而将它们放在/ etc / so /中
  • 文件需要全局可读或由rabbitmq用户或组拥有(docker容器内的数字ID为999),这需要由主机的sysadmin处理

docker run 示例:

    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 示例:

    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 :(得分:40)

您可以创建一个简单的Dockerfile来扩展基本图像的功能并创建一个默认用户。 您需要的Docker文件如下:

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

# Create Rabbitmq user
( sleep 5 ; \
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 $@

此脚本还在端口15672初始化并公开RabbitMQ webadmin。

答案 2 :(得分:11)

RabbitMQ image on Dockerhub的最新版本具有内置功能,可将默认用户名/密码从“ guest” /“ guest”更改为其他名称。

启动图像时,只需设置环境变量“ RABBITMQ_DEFAULT_USER”和“ RABBITMQ_DEFAULT_PASS”。

作为docker命令,您将像这样运行图像:

docker run \
-e RABBITMQ_DEFAULT_USER=test-user \
-e RABBITMQ_DEFAULT_PASS=test-user \
-p 5672:5672 \
rabbitmq

答案 3 :(得分:9)

我想补充一点,sudo的回复给了我很多帮助。但它仍然错过了一个添加到Dockerfile的命令。

rabbitmq.config和definitions.json文件应归rabbitmq用户所有。组。所以在添加文件后运行chown。

在我的案例中,完整的Dockerfile如下:

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"]

rabbitmq.config文件的以下内容是默认图像配置的合并以及添加的定义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 } 

        ]}
    ]}
].

可以从概览选项卡中的管理界面导出定义文件。

因此,您首先要创建一个正常的“空”' rabbitmq容器。定义您喜欢的任何用户,交换和队列。然后进入管理界面,导出定义并使用上述文件创建自己的图像。

下载定义是在您自己的密码的定义文件中获取正确密码哈希的最简单方法。如果您不希望这样做,请按照此处所述的说明(https://www.rabbitmq.com/passwords.html)生成正确的哈希值。

答案 4 :(得分:4)

在我的情况下,上述sleep 5解决方案无法正常工作,因为RabbitMQ的启动时间更长且无法预测。发布解决方案,直到RabbitMQ启动并运行:

  • 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
    

答案 5 :(得分:2)

上述解决方案有一个警告:它们将在官方Rabbit docker映像中“禁用” docker-entrypoint.sh脚本present。这可能对您来说不是问题。这个脚本创建了初始的RabbitMQ配置文件。添加一些很好的默认值(例如,如果容器运行时有内存限制,则为总内存限制)。

如果要保持完全兼容性,而又不想“禁用”此脚本,则可以使用以下方法。它将使用admin密码添加一个额外的admin用户,并保持guest用户不变。这对开发很有用。

此方法使用definitions.json文件通过管理插件初始化用户。为了通知插件definitions.json文件,我们使用RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS环境变量(而不是rabbitmq.conf文件)。

创建definitions.json文件:

{
  "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": []
}

创建自定义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\""

使用以下命令构建映像: docker build --tag myrabbit:1.0.0 .

然后运行它: docker run -d -p 5672:5672 -p 15672:15672 --restart unless-stopped --name rabbitmq myrabbit:1.0.0

答案 6 :(得分:0)

以下是我添加非特权用户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

的示例

答案 7 :(得分:0)

我必须对接受的答案中的脚本进行一些更改,才能根据上面的评论使脚本正常工作。

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

答案 8 :(得分:0)

使用RabbitMQ 3.7和更新的Rabbitmq.conf(sysctl)配置格式,以下在Docker中使用默认用户和队列设置RabbitMQ,您可以选择在dockerfile中添加以下RUN命令以创建用户...

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命令来构建和运行容器...

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

答案 9 :(得分:0)

在Kubernetes中,类似于@sudo的答案;可以通过ConfigMap和卷将definitions.json文件加载到容器中。

ConfigMap rabbitmq-definitions-configmap定义为从文件创建的configmap,目标为definitions.json。

您也可以对rabbitmq.config文件执行相同的操作。

请注意mountPathsubPath的用法,仅使用mountPath对我不起作用。

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

答案 10 :(得分:0)

就我而言,我想知道是否可以通过简单地挂载数据文件夹来转储 docker 容器 user/vhost/data。

我找到了以下文档:https://www.rabbitmq.com/backup.html,帮助太大了。


目前,我确实将 /var/lib/rabbitmq 卷挂载到主机,但是当容器重新创建时,用户和虚拟主机的配置就消失了。

很快我意识到在重新创建容器后,会生成一个具有不同 ID 的新数据集。

所以旧数据还在,只是id断了。

在我的示例中,0df72ae1a7a5 是旧的,当我创建一个新的 268bac197c69 时,旧数据不再处于活动状态。

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 rabbit@0df72ae1a7a5.pid
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 rabbit@268bac197c69.pid

在容器中,以下命令显示当前的活动id:

rabbitmqctl eval 'rabbit_mnesia:dir().'

它打印 "/var/lib/rabbitmq/mnesia/rabbit@268bac197c69",即当前新创建的一个。

现在问题简化为:

<块引用>

容器重新创建时如何用特定的旧id恢复旧数据?

很快,我发现当前id和容器主机名是一样的,是容器创建时随机生成的!

那么如何将 id 与特定值绑定?我查看了 docker-hub rabbitmq 页面:https://hub.docker.com/_/rabbitmq

<块引用>

关于 RabbitMQ 需要注意的重要事情之一是它根据它所谓的“节点名称”存储数据,默认为主机名。这对于在 Docker 中的使用意味着我们应该为每个守护进程显式指定 -h/--hostname 以便我们不会获得随机主机名并可以跟踪我们的数据:

最后的解决方案来了,我们只需要将 hostname 指定为特定值,当容器重新创建时,一切都会自动返回。


最终解决方案:

只需在我们的 docker-compose 部分添加主机名设置:

注意:主机名行和卷行很重要。

  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

答案 11 :(得分:0)

此处的其他一些解决方案无法使用 TLS,因为它们禁用了父入口点。其他人有不必要的步骤,因为父映像有一个未记录的功能,如果它存在于 /etc/rabbitmq 下,它将使用 definition.json。

这似乎是最简单的方法:

Dockerfile

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

definitions.json - 编辑以满足您的用户/虚拟主机/权限需求

{
"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": []
}

答案 12 :(得分:-3)

您可以创建新图像并使用rabbitmqctl命令行。

例如使用此Dockerfile:

FROM rabbitmq
# rabbitmqctl command requires to start the rabbitmq server 
RUN service rabbitmq-server start
RUN /usr/lib/rabbitmq/bin/rabbitmqctl add_user test-user mypassword
RUN /usr/lib/rabbitmq/bin/rabbitmqctl add_vhost myvhost 
RUN /usr/lib/rabbitmq/bin/rabbitmqctl set_permissions -p /myvhost test-user ".*" ".*" ".*"

使用

构建图像
sudo docker build -t anImageName .

我没有测试我的答案,我不能在工作中使用docker