Docker 安装 RabbitMQ
大约 11 分钟约 3154 字
Docker 安装 RabbitMQ
简介
RabbitMQ 是一个开源的消息代理软件(Message Broker),实现了高级消息队列协议(AMQP)。它由 Erlang 语言编写,以高可靠性、灵活的路由规则和丰富的管理插件著称。在微服务架构中,RabbitMQ 常用于服务间的异步通信、任务队列、日志收集和流量削峰等场景。
RabbitMQ 提供了一个功能完善的 Web 管理界面(Management Plugin),可以方便地监控队列状态、管理交换器和绑定关系。使用 Docker 部署 RabbitMQ 可以快速搭建开发和测试环境,通过合理的配置也能满足中小型生产环境的需求。
本文将详细介绍使用 Docker 部署 RabbitMQ 的完整流程,包括容器配置、用户管理、队列管理、插件启用、性能优化以及常见问题的排查。
核心概念
在开始部署之前,了解 RabbitMQ 的核心概念有助于后续的管理和运维:
- Producer(生产者):发送消息的应用程序
- Consumer(消费者):接收消息的应用程序
- Exchange(交换器):接收生产者发送的消息,根据路由规则将消息投递到队列
- Queue(队列):存储消息的缓冲区,消费者从队列中获取消息
- Binding(绑定):交换器和队列之间的关联关系
- Routing Key(路由键):生产者发送消息时指定的键,交换器根据它决定投递到哪个队列
- Virtual Host(虚拟主机):类似 MySQL 的数据库概念,用于隔离不同业务的队列和交换器
环境准备
系统要求
| 项目 | 最低要求 | 推荐配置 |
|---|---|---|
| 操作系统 | CentOS 7+ / Ubuntu 18.04+ | CentOS 7.9 |
| 内存 | 1GB | 2GB+ |
| 磁盘 | 10GB | 50GB+ |
| Docker | 19.03+ | 最新稳定版 |
端口规划
| 端口 | 协议 | 说明 |
|---|---|---|
| 5672 | AMQP | 消息协议通信端口 |
| 15672 | HTTP | Web 管理界面端口 |
| 25672 | Erlang | 节点间通信端口(集群使用) |
| 61613 | STOMP | STOMP 协议端口(可选) |
| 1883 | MQTT | MQTT 协议端口(可选) |
第一步:创建宿主机目录
# 创建 RabbitMQ 数据存储目录
mkdir -p /usr/local/docker/rabbitmq/1/lib
# 创建日志目录
mkdir -p /usr/local/docker/rabbitmq/1/log
# 设置日志目录权限
chmod -R 777 /usr/local/docker/rabbitmq/1/log目录说明
lib目录:存储 RabbitMQ 的持久化数据(消息、队列、交换器等)log目录:存储 RabbitMQ 的运行日志- 目录权限建议设为
777或根据容器内 rabbitmq 用户的 UID 设置,避免权限问题
第二步:运行容器
docker run -d \
--restart=always \
--hostname rabbitmq \
--name rabbitmq \
-p 15672:15672 \
-p 5672:5672 \
-e RABBITMQ_DEFAULT_USER=admin \
-e RABBITMQ_DEFAULT_PASS=your_strong_password \
-e RABBITMQ_ERLANG_COOKIE='rabbitmq_cluster_cookie' \
--privileged=true \
-v /usr/local/docker/rabbitmq/1/lib:/var/lib/rabbitmq \
-v /usr/local/docker/rabbitmq/1/log:/var/log/rabbitmq \
rabbitmq:3-management参数详解
| 参数 | 说明 |
|---|---|
-d | 后台模式运行容器 |
--restart=always | Docker 服务重启后容器自动启动 |
--hostname rabbitmq | 自定义容器的 hostname(RabbitMQ 集群依赖 hostname) |
--name rabbitmq | 指定容器名称 |
-p 15672:15672 | Web 管理界面端口映射 |
-p 5672:5672 | AMQP 协议通信端口映射 |
-e RABBITMQ_DEFAULT_USER=admin | 设置默认管理员用户名 |
-e RABBITMQ_DEFAULT_PASS=your_strong_password | 设置默认管理员密码 |
-e RABBITMQ_ERLANG_COOKIE='rabbitmq_cluster_cookie' | Erlang Cookie,集群节点间通信的密钥 |
--privileged=true | 赋予容器真正的 root 权限,解决挂载目录的权限问题 |
-v /usr/local/docker/rabbitmq/1/lib:/var/lib/rabbitmq | 持久化数据目录挂载 |
-v /usr/local/docker/rabbitmq/1/log:/var/log/rabbitmq | 日志目录挂载 |
rabbitmq:3-management | 镜像名(包含管理插件的版本) |
镜像选择
RabbitMQ 官方提供两种镜像:
rabbitmq:3:基础版,不包含管理界面rabbitmq:3-management:包含 Web 管理界面,推荐使用
建议指定具体版本号,如 rabbitmq:3.12-management
第三步:防火墙配置
# 查看防火墙当前的放行端口列表
firewall-cmd --list-ports
# 添加 Web 管理界面端口
firewall-cmd --add-port=15672/tcp --permanent
# 添加 AMQP 通信端口
firewall-cmd --add-port=5672/tcp --permanent
# 重新加载防火墙
firewall-cmd --reload
# 验证端口放行
firewall-cmd --list-ports第四步:访问管理控制台
在浏览器中打开以下地址:
http://<服务器IP>:15672使用启动时设置的管理员账号密码登录:
- 用户名:
admin - 密码:
your_strong_password
管理界面主要功能包括:
- Overview:总览面板,显示消息速率、节点信息等
- Connections:查看当前连接的客户端
- Channels:查看当前通道
- Exchanges:管理交换器
- Queues:管理队列
- Admin:用户和权限管理
用户与权限管理
命令行管理用户
# 进入 RabbitMQ 容器
docker exec -it rabbitmq bash
# 查看所有用户
rabbitmqctl list_users
# 添加新用户
rabbitmqctl add_user dev_user dev_password
# 设置用户为管理员
rabbitmqctl set_user_tags dev_user administrator
# 设置用户权限(对指定虚拟主机)
rabbitmqctl set_permissions -p / dev_user ".*" ".*" ".*"
# 查看用户权限
rabbitmqctl list_permissions -p /
# 修改密码
rabbitmqctl change_password dev_user new_password
# 删除用户
rabbitmqctl delete_user dev_user权限说明
RabbitMQ 的用户权限由三个正则表达式控制:
| 权限 | 说明 |
|---|---|
configure | 用户的队列、交换器等资源的创建和删除权限 |
write | 向交换器发布消息的权限 |
read | 从队列消费消息的权限 |
# 设置精确权限
rabbitmqctl set_permissions -p my_vhost my_user \
"^my-.*$" \ # configure: 只能管理 my- 开头的资源
"^my-.*$" \ # write: 只能向 my- 开头的交换器发消息
"^my-.*$" # read: 只能从 my- 开头的队列消费Virtual Host 管理
# 进入容器
docker exec -it rabbitmq bash
# 创建虚拟主机
rabbitmqctl add_vhost my_app
# 列出所有虚拟主机
rabbitmqctl list_vhosts
# 设置用户对虚拟主机的权限
rabbitmqctl set_permissions -p my_app my_user ".*" ".*" ".*"
# 删除虚拟主机
rabbitmqctl delete_vhost my_app
# 清除虚拟主机中的所有数据
rabbitmqctl reset -p my_app常见问题排查
登录控制台出现"连接不是私密连接"
问题:浏览器访问 http://ip:15672 时提示"你与此网站的连接不是私密连接"原因:创建容器时密码可能未能成功设置进去。
解决方案:
# 1. 进入 RabbitMQ 容器
docker exec -it rabbitmq bash
# 2. 查看当前用户列表
rabbitmqctl list_users
# 3. 重新设置密码
rabbitmqctl change_password admin your_new_password
# 4. 退出容器重新登录
exit
# 然后在浏览器中刷新页面,使用新密码登录容器启动失败
# 查看容器日志
docker logs rabbitmq
# 常见原因1:端口被占用
ss -tlnp | grep 5672
ss -tlnp | grep 15672
# 常见原因2:目录权限不足
ls -la /usr/local/docker/rabbitmq/1/lib
ls -la /usr/local/docker/rabbitmq/1/log
# 解决权限问题
chown -R 999:999 /usr/local/docker/rabbitmq/1/lib
chmod -R 755 /usr/local/docker/rabbitmq/1/log
# 常见原因3:Erlang Cookie 不一致(集群模式下)
docker exec rabbitmq cat /var/lib/rabbitmq/.erlang.cookie消息堆积问题
# 查看队列状态
docker exec rabbitmq rabbitmqctl list_queues name messages messages_ready messages_unacknowledged
# 查看消费者数量
docker exec rabbitmq rabbitmqctl list_queues name consumers
# 查看未确认的消息
docker exec rabbitmq rabbitmqctl list_queues name messages_unacknowledged插件管理
# 进入容器
docker exec -it rabbitmq bash
# 查看已安装的插件
rabbitmq-plugins list
# 启用插件
rabbitmq-plugins enable rabbitmq_management # 管理界面
rabbitmq-plugins enable rabbitmq_shovel # 跨集群消息转发
rabbitmq-plugins enable rabbitmq_federation # 联邦插件
rabbitmq-plugins enable rabbitmq_delayed_message_exchange # 延迟消息
# 禁用插件
rabbitmq-plugins disable rabbitmq_shovel
# 查看已启用的插件
rabbitmq-plugins list -e性能优化建议
内存与磁盘限制
# 在启动命令中添加内存水位线参数
docker run -d \
--name rabbitmq \
-p 15672:15672 \
-p 5672:5672 \
-e RABBITMQ_DEFAULT_USER=admin \
-e RABBITMQ_DEFAULT_PASS=your_strong_password \
-e RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="-rabbit vm_memory_high_watermark 0.6" \
-v /usr/local/docker/rabbitmq/1/lib:/var/lib/rabbitmq \
-v /usr/local/docker/rabbitmq/1/log:/var/log/rabbitmq \
--restart=always \
rabbitmq:3-management策略管理
# 创建消息过期策略(所有队列消息 7 天后过期)
docker exec rabbitmq rabbitmqctl set_policy expiry ".*" \
'{"expires": 604800000}' --apply-to queues
# 创建死信交换器策略
docker exec rabbitmq rabbitmqctl set_policy dead_letter "dlx-.*" \
'{"dead-letter-exchange": "my-dlx"}' --apply-to queues
# 创建镜像队列策略(集群模式下高可用)
docker exec rabbitmq rabbitmqctl set_policy ha-all ".*" \
'{"ha-mode": "all", "ha-sync-mode": "automatic"}' --apply-to queues
# 查看所有策略
docker exec rabbitmq rabbitmqctl list_policiesDocker Compose 部署
# docker-compose-rabbitmq.yml
version: '3.8'
services:
rabbitmq:
image: rabbitmq:3.12-management
container_name: rabbitmq
restart: always
hostname: rabbitmq
ports:
- "5672:5672"
- "15672:15672"
environment:
RABBITMQ_DEFAULT_USER: admin
RABBITMQ_DEFAULT_PASS: your_strong_password
RABBITMQ_ERLANG_COOKIE: rabbitmq_cluster_cookie
TZ: Asia/Shanghai
volumes:
- ./rabbitmq/data:/var/lib/rabbitmq
- ./rabbitmq/log:/var/log/rabbitmq
networks:
- app-net
networks:
app-net:
driver: bridgeRabbitMQ 集群部署
Docker Compose 三节点集群
version: "3.8"
services:
rabbitmq1:
image: rabbitmq:3.12-management
container_name: rabbitmq1
hostname: rabbitmq1
restart: always
ports:
- "5672:5672"
- "15672:15672"
- "25672:25672"
environment:
RABBITMQ_ERLANG_COOKIE: rabbitmq_cluster_secret_cookie
RABBITMQ_DEFAULT_USER: admin
RABBITMQ_DEFAULT_PASS: RabbitmqPass123
TZ: Asia/Shanghai
volumes:
- ./rabbitmq1/data:/var/lib/rabbitmq
- ./rabbitmq1/log:/var/log/rabbitmq
networks:
- rabbitmq-cluster-net
rabbitmq2:
image: rabbitmq:3.12-management
container_name: rabbitmq2
hostname: rabbitmq2
restart: always
ports:
- "5673:5672"
- "15673:15672"
- "25673:25672"
environment:
RABBITMQ_ERLANG_COOKIE: rabbitmq_cluster_secret_cookie
TZ: Asia/Shanghai
volumes:
- ./rabbitmq2/data:/var/lib/rabbitmq
- ./rabbitmq2/log:/var/log/rabbitmq
networks:
- rabbitmq-cluster-net
depends_on:
- rabbitmq1
rabbitmq3:
image: rabbitmq:3.12-management
container_name: rabbitmq3
hostname: rabbitmq3
restart: always
ports:
- "5674:5672"
- "15674:15672"
- "25674:25672"
environment:
RABBITMQ_ERLANG_COOKIE: rabbitmq_cluster_secret_cookie
TZ: Asia/Shanghai
volumes:
- ./rabbitmq3/data:/var/lib/rabbitmq
- ./rabbitmq3/log:/var/log/rabbitmq
networks:
- rabbitmq-cluster-net
depends_on:
- rabbitmq1
networks:
rabbitmq-cluster-net:
driver: bridge集群节点加入
# 1. 启动所有节点
docker-compose up -d
# 2. 停止 rabbitmq2 和 rabbitmq3 的应用
docker exec rabbitmq2 rabbitmqctl stop_app
docker exec rabbitmq3 rabbitmqctl stop_app
# 3. 将 rabbitmq2 加入 rabbitmq1 的集群
docker exec rabbitmq2 rabbitmqctl join_cluster rabbitmq@rabbitmq1
# 4. 将 rabbitmq3 加入 rabbitmq1 的集群
docker exec rabbitmq3 rabbitmqctl join_cluster rabbitmq@rabbitmq1
# 5. 启动 rabbitmq2 和 rabbitmq3 的应用
docker exec rabbitmq2 rabbitmqctl start_app
docker exec rabbitmq3 rabbitmqctl start_app
# 6. 查看集群状态
docker exec rabbitmq1 rabbitmqctl cluster_status
# 7. 在节点 2 上设置用户(集群用户不会自动同步)
docker exec rabbitmq2 rabbitmqctl add_user admin RabbitmqPass123
docker exec rabbitmq2 rabbitmqctl set_user_tags admin administrator
docker exec rabbitmq2 rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"镜像队列配置
# 镜像队列确保队列数据在多个节点上有副本
# 当主节点故障时,从节点自动提升为主节点
# 创建 ha-all 策略:所有队列在所有节点上都有镜像
docker exec rabbitmq1 rabbitmqctl set_policy ha-all ".*" \
'{"ha-mode":"all","ha-sync-mode":"automatic","ha-sync-batch-size":10}' \
--apply-to queues
# 创建 ha-exactly 策略:每个队列恰好有 2 个副本
docker exec rabbitmq1 rabbitmqctl set_policy ha-two ".*" \
'{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}' \
--apply-to queues
# 创建 ha-nodes 策略:指定哪些节点作为镜像
docker exec rabbitmq1 rabbitmqctl set_policy ha-nodes ".*" \
'{"ha-mode":"nodes","ha-params":["rabbit@rabbitmq1","rabbit@rabbitmq2"]}' \
--apply-to queues
# 查看策略
docker exec rabbitmq1 rabbitmqctl list_policies
# 查看队列同步状态
docker exec rabbitmq1 rabbitmqctl list_queues name policy slave_pids synchronised_slave_pidsRabbitMQ 交换器与路由
交换器类型
| 类型 | 说明 | 适用场景 |
|---|---|---|
| Direct | 精确匹配 routing key | 点对点消息传递 |
| Fanout | 广播到所有绑定队列 | 日志广播、事件通知 |
| Topic | 通配符匹配 routing key | 多条件路由 |
| Headers | 基于消息头匹配 | 复杂路由规则 |
命令行管理交换器和队列
# 声明交换器
docker exec rabbitmq rabbitmqadmin declare exchange name=my-direct-exchange type=direct durable=true
# 声明队列
docker exec rabbitmq rabbitmqadmin declare queue name=my-queue durable=true
# 绑定队列到交换器
docker exec rabbitmq rabbitmqadmin declare binding source=my-direct-exchange destination=my-queue routing_key=my.key
# 发送测试消息
docker exec rabbitmq rabbitmqadmin publish exchange=my-direct-exchange routing_key=my.key payload="Hello RabbitMQ"
# 消费消息
docker exec rabbitmq rabbitmqadmin get queue=my-queue count=1
# 列出所有交换器
docker exec rabbitmq rabbitmqctl list_exchanges
# 列出所有队列
docker exec rabbitmq rabbitmqctl list_queues name messages consumers
# 列出所有绑定
docker exec rabbitmq rabbitmqctl list_bindings
# 删除队列
docker exec rabbitmq rabbitmqctl delete_queue my-queue
# 清空队列(保留队列但删除消息)
docker exec rabbitmq rabbitmqctl purge_queue my-queueRabbitMQ 监控与运维
监控指标
# 查看节点状态
docker exec rabbitmq rabbitmqctl status
# 查看集群节点状态
docker exec rabbitmq rabbitmqctl cluster_status
# 查看连接数
docker exec rabbitmq rabbitmqctl list_connections
# 查看通道数
docker exec rabbitmq rabbitmqctl list_channels
# 查看消费者列表
docker exec rabbitmq rabbitmqctl list_consumers
# 查看内存使用
docker exec rabbitmq rabbitmqctl status | grep -A 10 memory
# 查看磁盘使用
docker exec rabbitmq rabbitmqctl status | grep -A 5 disk
# 查看文件描述符使用
docker exec rabbitmq rabbitmqctl status | grep -A 5 file_descriptors
# 启用 Prometheus 插件(暴露监控指标)
docker exec rabbitmq rabbitmq-plugins enable rabbitmq_prometheus
# 指标地址:http://<ip>:15692/metrics常见运维操作
# 消息堆积处理
# 1. 查看堆积情况
docker exec rabbitmq rabbitmqctl list_queues name messages messages_ready messages_unacknowledged
# 2. 如果消费者处理不过来,考虑:
# - 增加消费者数量
# - 检查消费者处理速度
# - 设置消息 TTL 避免无限堆积
# 3. 清空积压队列(谨慎操作)
docker exec rabbitmq rabbitmqctl purge_queue my-queue
# 死信队列处理
# 1. 查看死信队列中的消息
docker exec rabbitmq rabbitmqadmin get queue=dlx-queue count=10
# 2. 重新投递死信消息
# 需要通过管理界面或程序手动将死信消息重新发布到原队列
# 节点下线处理
# 1. 优雅关闭节点(等待消息处理完成)
docker exec rabbitmq rabbitmqctl stop_app
# 2. 确认其他节点已接管镜像队列
docker exec rabbitmq2 rabbitmqctl cluster_status
# 3. 移除节点(永久下线)
docker exec rabbitmq2 rabbitmqctl forget_cluster_node rabbitmq@rabbitmq3RabbitMQ 与 .NET 集成
生产者配置示例
# .NET 中的连接字符串格式
amqp://admin:RabbitmqPass123@192.168.1.100:5672/my_vhost
# 确认虚拟主机存在
docker exec rabbitmq rabbitmqctl add_vhost my_vhost
docker exec rabbitmq rabbitmqctl set_permissions -p my_vhost admin ".*" ".*" ".*"备份与恢复
# 导出配置(不包含消息)
docker exec rabbitmq rabbitmqctl export_definitions /tmp/definitions.json
docker cp rabbitmq:/tmp/definitions.json ./rabbitmq_backup/
# 导入配置
docker cp ./rabbitmq_backup/definitions.json rabbitmq:/tmp/
docker exec rabbitmq rabbitmqctl import_definitions /tmp/definitions.json
# 备份数据目录(包含消息,需要停止 RabbitMQ)
docker stop rabbitmq
tar czf rabbitmq_data_backup_$(date +%Y%m%d).tar.gz \
/usr/local/docker/rabbitmq/1/lib/
docker start rabbitmq