Apache BifroMQ 3.3.5 Docker Compose 部署指南
Apache BifroMQ 3.3.5 Docker Compose 部署指南:自建镜像注入官方发行包,MEM_LIMIT 约束 JVM 堆 512MB 内,数据日志卷持久化与端口映射,mosquitto 完成收发与重启持久化验证,均实测
Apache BifroMQ 3.3.5 Docker Compose 部署指南
目标:使用 Docker Compose 编排 Apache BifroMQ 3.3.5 单机版:基于 eclipse-temurin:17-jre 自建镜像注入官方发行包,通过
MEM_LIMIT环境变量把 JVM 堆约束在 512MB 以内(实测自动推导 -Xms179m -Xmx358m),数据/日志卷持久化,端口映射到宿主机,并用 mosquitto 客户端完成 QoS0/QoS1/保留消息端到端收发与重启持久化验证。以下命令与回显均为实际执行结果。
一、环境信息
- 宿主机:Ubuntu 22.04.5 LTS(x86_64),Docker Compose v5.5.1
- Java 基础镜像:eclipse-temurin:17-jre(本地已有;BifroMQ 硬性要求 JDK 17+)
- Apache BifroMQ:3.3.5(官方
standalone发行包bifromq-3.3.5-standalone.tar.gz,126,286,685 字节,sha256dd739c43b441dd5008f81543911bea5ec3b3662fdb52d3a9fbd187e902ca76b9) - 镜像:自建
bifromq:3.3.5 - 端口映射:宿主机 11883→1883(MQTT)、18080→8080(WebSocket)、18091→8091(HTTP API)、19090→9090(Prometheus)
- 客户端工具:mosquitto-clients 2.0.11(在另一台 Ubuntu 实机上执行验证命令)
💡 说明:官方也发布 Docker 镜像(
bifromq/bifromq,官方文档示例docker run -d -p 1883:1883 bifromq/bifromq:latest)。本文采用「自建镜像」方式:发行包已在本地并完成 sha256 校验,自建镜像版本可控、离线可部署。两种方式的环境变量(MEM_LIMIT/JVM_HEAP_OPTS 等)完全一致。
二、目录结构
/opt/bifromq-compose/
├── Dockerfile
├── compose.yaml
└── bifromq-3.3.5-standalone.tar.gz # 官方发行包(已校验 sha256)
三、Dockerfile
FROM eclipse-temurin:17-jre
WORKDIR /workdir
COPY bifromq-3.3.5-standalone.tar.gz /tmp/bifromq.tar.gz
RUN tar -zxf /tmp/bifromq.tar.gz --strip-components 1 -C /workdir/ \
&& rm -f /tmp/bifromq.tar.gz \
&& chmod +x /workdir/bin/*.sh
EXPOSE 1883 1884 8080 8443 8091 9090
ENTRYPOINT ["/workdir/bin/standalone.sh"]
CMD ["start", "-fg"]
要点:
-fg前台模式启动(standalone.sh start -fg),JVM 进程成为 1 号进程,停止信号可直接送达,符合镜像最佳实践;WORKDIR /workdir与官方镜像布局一致,data/、logs/由启动脚本自动在其下创建,便于挂卷;- 基础镜像自带 JRE 17,满足启动脚本的 Java 版本硬校验。
四、compose.yaml
services:
bifromq:
image: bifromq:3.3.5
build:
context: .
dockerfile: Dockerfile
container_name: bifromq-standalone
hostname: bifromq-mqtt
ports:
- "11883:1883"
- "18080:8080"
- "18091:8091"
- "19090:9090"
environment:
MEM_LIMIT: "536870912" # 512MB,JVM 堆按 70% 自动推导
volumes:
- bifromq-data:/workdir/data # 会话/订阅/保留消息持久化
- bifromq-logs:/workdir/logs
restart: unless-stopped
volumes:
bifromq-data:
bifromq-logs:
💡
MEM_LIMIT是官方启动脚本识别的内存限额变量(单位:字节):不设JVM_HEAP_OPTS时,堆上限 = MEM_LIMIT × 70%,堆下限为其一半,MaxDirectMemorySize = MEM_LIMIT × 20%。512MB 时实测推导结果见下文第六节。
五、构建并启动
cd /opt/bifromq-compose
docker compose up -d --build
docker compose ps
回显:
[+] Running 2/2
✔ Container bifromq-standalone Started
NAME IMAGE STATUS
bifromq-standalone bifromq:3.3.5 Up 40 seconds
⚠️ 实测坑:在默认地址池已被占满的宿主机上,Compose 创建网络会报
all predefined address pools have been fully subnetted。此时需在 compose.yaml 中显式指定一个未占用网段(服务级引用 networks 时不能内联 ipam,需放顶层 networks 定义):
services:
bifromq:
# ...(其余不变)
networks:
- bifromq-net
networks:
bifromq-net:
driver: bridge
ipam:
config:
- subnet: 192.168.144.0/24 # 换成本机未占用网段
常规宿主机无需此配置。
六、验证 JVM 堆约束(MEM_LIMIT 生效实测)
docker exec bifromq-standalone ps aux | grep -oE "\-Xms[0-9]+m \-Xmx[0-9]+m" | head -1
回显:
-Xms179m -Xmx358m
与公式完全吻合:512MB × 70% = 358MB(Xmx),其一半 179MB(Xms),MaxDirectMemorySize 实测为 107374180 字节(512MB × 20%)。无需在镜像里改任何脚本,仅靠 MEM_LIMIT 环境变量即完成堆约束。
💡 若想精确指定堆而不走推导,改设
JVM_HEAP_OPTS: "-Xms256m -Xmx512m"即可(实测jps -v可见-Xms256m -Xmx512m)。
七、MQTT 端到端收发验证
在另一台 Ubuntu 实机(装有 mosquitto-clients)上,对宿主机 11883 端口执行:
连接与订阅:
mosquitto_sub -h <宿主机IP> -p 11883 -t "e2e/#" -V mqttv5 -d
Client ... received CONNACK (0)
Subscribed (mid: 1): 0
发布(QoS1/QoS0/保留消息各一条):
mosquitto_pub -h <宿主机IP> -p 11883 -t e2e/q1 -m "e2e-qos1-message" -q 1 -d
mosquitto_pub -h <宿主机IP> -p 11883 -t e2e/q0 -m "e2e-qos0-message" -q 0
mosquitto_pub -h <宿主机IP> -p 11883 -t e2e/retain -m "e2e-retained" -q 1 -r
Client (null) received PUBACK (Mid: 1, RC:0)
订阅端实际收到(三条全部通过):
e2e/q1 e2e-qos1-message
e2e/q0 e2e-qos0-message
e2e/retain e2e-retained
保留消息重投递(新建订阅者立即收到):
mosquitto_sub -h <宿主机IP> -p 11883 -t "e2e/retain" -C 1 -W 4
e2e-retained
八、重启持久化验证
docker compose restart
回显:
Container bifromq-standalone Started
等待约 30 秒服务就绪后,新订阅者仍能收到重启前发布的保留消息:
e2e-retained
数据卷(bifromq-data)持久化生效;会话、订阅关系与保留消息跨重启保留。
九、Prometheus 指标与管理 API
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:19090/metrics
200
指标由内置 demo 插件导出,含 basecluster_*(集群成员/健康分)、basekv_*(存储 range/引擎)、ppln_*(RPC 管道)及 MQTT 各子系统指标。
HTTP 管理 API(18091)按 Header 传参(注意默认绑定 site-local 地址,映射前可接受 127.0.0.1 不通为正常):
curl -X POST http://127.0.0.1:18091/pub \
-H "req_id: 1" -H "tenant_id: bifromq" -H "topic: rest/verify" \
-H "qos: 0" -H "client_type: curl" -H "client_meta_lang: zh" \
--data-binary "hello"
回显:
NO_MATCH
HTTP 200 + NO_MATCH 表示发布成功且无匹配订阅者。
十、常用运维命令
docker compose ps # 服务状态
docker compose logs -f --tail 100 # 日志(含启动序列 MQTT broker started)
docker compose restart # 重启(数据卷保留)
docker compose down # 停止并删除服务(数据卷保留,加 -v 才删卷)
docker compose up -d # 再次拉起
docker exec bifromq-standalone ls /workdir/logs # 宿主机查看日志文件
日志确认启动完成(docker compose logs 中出现):
Inbox store started / Retain store started / Dist worker started
MQTT broker started
API server started
十一、常见问题
11.1 拉起后 1883 连不上
首次启动需 30~60 秒完成内部存储引导;用 docker compose logs -f 看到 MQTT broker started 后再连。
11.2 网络创建报 all predefined address pools have been fully subnetted
见第五节:显式指定未占用网段。
11.3 订阅返回 128(Not authorized)
与镜像内 /tmp 挂载策略有关:若底层运行时把 /tmp 挂成 noexec,netty 原生库无法加载,内部 dist 子系统异常(日志有 NativeLibraryLoader ... cannot be executed ... "noexec" flag 告警与 Batcher not found 报错)。确保 /tmp 可执行,或为服务挂载可执行空目录覆盖 /tmp(- /tmp/bifromq-tmp:/tmp,且宿主机该目录不带 noexec)后重启。
11.4 想改端口或开 TLS
镜像内 /workdir/conf/standalone.yml 为配置入口:mqttServerConfig.tcpListener.port、TLS 监听(1884/8443)、apiServerConfig.httpPort 等均在此调整;可再挂载一个只读卷覆盖配置文件(如 - ./standalone.yml:/workdir/conf/standalone.yml:ro)后 docker compose restart。
十二、参考链接
- 官网 Docker 部署文档(3.3.x):https://bifromq.io/docs/3.3.x/installation/
- GitHub Releases:https://github.com/apache/bifromq/releases
- 配置手册:https://bifromq.io/docs/3.3.x/admin_guide/configuration/config_file_manual/