Docker 部署 RabbitMQ 集群时,持久化存储的核心是把数据目录挂载到宿主机,同时确保集群节点间的 Cookie 一致。但仅配置 Cookie 和数据卷并不会自动形成集群,必须显式执行加入命令,否则节点将独立运行导致数据分片。
先说结论:生产环境必须挂载数据卷,集群节点间共享相同的 Erlang Cookie,且需手动执行 join 命令组建集群。
- 适合:需要重启容器后保留队列、消息及集群关系的场景。
- 先准备:宿主机目录权限(UID 999)、统一的.erlang.cookie、固定的容器主机名、自定义 Docker 网络。
- 验收:重启容器后检查集群状态是否正常,历史消息是否还在。
前置准备:权限与网络
RabbitMQ 官方镜像默认使用 UID 999 运行。若宿主机目录权限不足,容器将启动失败。建议提前创建目录并修正权限。
mkdir -p ./data/rabbitmq1 ./data/rabbitmq2
chown -R 999:999 ./data同时,为确保容器间可通过主机名通信,建议创建自定义桥接网络。
Docker Compose 配置示例
以下配置包含了持久化卷、权限控制、网络配置及 Cookie 统一设置。
version: '3.8'
services:
rabbitmq1:
image: rabbitmq:3-management
hostname: rabbitmq1
user: "999:999"
volumes:
- ./data/rabbitmq1:/var/lib/rabbitmq
environment:
- RABBITMQ_ERLANG_COOKIE=SECRET_COOKIE
networks:
- rabbitmq-net
ports:
- "15672:15672"
rabbitmq2:
image: rabbitmq:3-management
hostname: rabbitmq2
user: "999:999"
volumes:
- ./data/rabbitmq2:/var/lib/rabbitmq
environment:
- RABBITMQ_ERLANG_COOKIE=SECRET_COOKIE
networks:
- rabbitmq-net
depends_on:
- rabbitmq1
networks:
rabbitmq-net:
driver: bridge关键步骤:手动组建集群
容器启动后节点是独立的,需在次要节点执行加入命令。以将 rabbitmq2 加入 rabbitmq1 为例:
# 1. 停止次要节点应用
docker-compose exec rabbitmq2 rabbitmqctl stop_app
# 2. 加入集群(指定主节点主机名)
docker-compose exec rabbitmq2 rabbitmqctl join_cluster rabbitmq1
# 3. 启动次要节点应用
docker-compose exec rabbitmq2 rabbitmqctl start_app若需重置集群,可使用rabbitmqctl forget_cluster_node清除关系。
验证是否生效
1. 检查集群状态:进入任意容器执行rabbitmqctl cluster_status,确认running_nodes列表中包含所有节点。
2. 验证数据持久化:发送一条持久化消息到队列,重启所有容器(docker-compose down后up -d),登录后查看消息是否依然存在。
3. 检查挂载点:在宿主机执行ls -lh ./data,确认各节点目录下有文件生成且大小随消息量变化。
常见坑与排查
1. 权限错误:日志报permission denied。解决方案:在宿主机执行chown -R 999:999 ./data或在 compose 中添加user: "999:999"。
2. Cookie 不一致:节点间 Cookie 不同会导致认证失败,集群无法建立。确保环境变量或文件内容完全一致。
3. 共享同一卷:不要将同一个宿主机目录挂载给多个容器节点,这会导致数据损坏。每个节点必须有独立的数据目录。
4. 网络隔离:集群节点间需要通信多个端口(如 4369, 25672),确保 Docker 网络模式允许互通,自定义网络可避免默认桥接网络的主机名解析问题。
参考来源
- RabbitMQ Official Documentation - Clustering: https://www.rabbitmq.com/clustering.html
- Docker Hub - RabbitMQ Image: https://hub.docker.com/_/rabbitmq
- RabbitMQ Official Documentation - Persistence: https://www.rabbitmq.com/persistence-conf.html