在物联网(IoT)开发中,Mosquitto 凭借其轻量、开源的特性,成为了最受欢迎的 MQTT 消息代理之一。这篇博文使用 Docker Compose 快速部署一个生产级的 Mosquitto 服务,开启账号密码认证,并打通 MQTT TCP 与 Websocket 双端口。
提示 :Mosquitto 官方 Docker 镜像内部以
mosquitto用户(UID=1883)运行。在宿主机挂载目录时,文件权限是最容易踩坑的地方,本文已提供最优解。
一、环境准备与目录规划
首先,拉取官方最新镜像:
bash
docker pull eclipse-mosquitto
若拉取镜像失败,可参考Debian11上无法拉取docker镜像问题的解决方案
为了便于统一管理配置、持久化数据和日志,我们在宿主机创建专属的项目目录:
bash
mkdir -p /mosquitto/{config,data,log}
cd /mosquitto
最终目录结构如下:
text
/mosquitto/
├── config/ # 存放 mosquitto.conf 和 pwfile
├── data/ # 持久化消息数据库
├── log/ # 运行日志
└── docker-compose.yml
二、编写核心配置文件
1. 创建 docker-compose.yml
在项目根目录创建 docker-compose.yml,填入以下配置(新版 Compose 已移除 version 字段):
yaml
services:
mosquitto:
image: eclipse-mosquitto
container_name: mosquitto
restart: always
ports:
- "1883:1883" # MQTT TCP 协议端口
- "9001:9001" # MQTT over Websocket 端口
volumes:
- ./config:/mosquitto/config
- ./data:/mosquitto/data
- ./log:/mosquitto/log
2. 编写 mosquitto.conf
在 ./config/ 目录下创建 mosquitto.conf:
ini
# 开启消息持久化,重启不丢消息
persistence true
persistence_location /mosquitto/data/
# 日志输出配置:同时输出到文件和控制台,方便 docker logs 查看
log_dest file /mosquitto/log/mosquitto.log
log_dest stdout
# 监听 MQTT TCP 端口
listener 1883
# 监听 Websocket 端口,供前端网页客户端使用
listener 9001
protocol websockets
# 生产环境安全配置:关闭匿名访问
allow_anonymous false
# 指定账号密码文件路径
password_file /mosquitto/config/pwfile
三、权限修正与账号初始化
1. 预创建密码文件并修正权限
为了避免容器启动时因权限不足报错,我们需要提前创建密码文件,并将整个目录授权给容器内的 mosquitto 用户(UID=1883):
bash
# 创建空的密码文件
touch ./config/pwfile
# 将目录归属修改为 1883:1883
chown -R 1883:1883 /mosquitto
2. 启动容器
在 /mosquitto 目录下执行:
bash
docker compose up -d
3. 创建 MQTT 登录账号
进入容器 Shell 添加用户。注意:-c 参数仅用于首次创建文件,文件已存在时切勿使用,否则会清空已有账号!
bash
# 进入容器
docker exec -it mosquitto sh
# 添加 admin 用户,注意 不加 -c
mosquitto_passwd /mosquitto/config/pwfile admin
按提示输入两次密码后,退出容器(exit)。
补充 :如果后续需要重置密码文件,可以先在宿主机执行
rm ./config/pwfile,再进容器使用mosquitto_passwd -c ...重新创建。
4. 重启服务使配置生效
修改密码文件后,必须重启 Mosquitto 才能加载:
bash
docker compose restart
四、通信验证测试
新开两个终端窗口,分别测试订阅和发布:
终端 A(订阅端):
bash
docker exec -it mosquitto mosquitto_sub -h localhost -t test -u admin -P 你的密码
终端 B(发布端):
bash
docker exec -it mosquitto mosquitto_pub -h localhost -t test -m "Hello MQTT Docker Compose" -u admin -P 你的密码
当终端 A 成功收到 "Hello MQTT Docker Compose" 消息时,代表 Broker 已经部署成功!

或者直接用MQTTX连接到broker 发布和订阅消息测试

五、日常运维速查
以下命令均需在 docker-compose.yml 所在目录执行:
bash
# 后台启动服务
docker compose up -d
# 停止并删除容器(保留 config/data/log 数据)
docker compose down
# 停止并删除容器 + 清空数据卷(!!! 慎用,会丢失持久化消息)
docker compose down -v
# 实时查看运行日志
docker compose logs -f
# 重启 Mosquitto
docker compose restart
六、生产环境安全建议
- 严禁匿名访问 :公网暴露必须设置
allow_anonymous false,并配置强密码。如有更高安全需求,建议配置 TLS 证书并使用 8883 加密端口。 - 防火墙放行 :云服务器需在控制台安全组放行
1883和9001端口;本地服务器需配置 iptables/ufw 放行。 - 最小权限原则 :不要图省事使用
chmod 777授权目录,坚持使用chown 1883:1883属主方式。 - 定期备份 :定期备份
/mosquitto/config目录,妥善保存密码文件与核心配置。
七、常见报错排错指南
| 报错现象 | 原因分析 | 解决方案 |
|---|---|---|
| 容器状态 Restarting(13) | 挂载目录权限不对,mosquitto 用户无法读写日志或密码文件 | 执行 chown -R 1883:1883 /mosquitto |
| Error: Unable to open pwfile | pwfile 文件不存在,或文件属主不是 1883 | 提前创建空 pwfile,并修改属主为 1883:1883 |
| File exists (添加用户时) | 密码文件已存在,但错误地使用了 -c 参数 |
去掉 -c 参数直接添加;若需重建,先删除 pwfile |
WARN: attribute version is obsolete |
新版 Docker Compose V2 不再需要 version 字段 | 删除 docker-compose.yml 首行的 version: "3.8" 即可,不影响运行 |
| Conflict. The container name "/mosquitto" is already in use | 之前用 docker run 创建的同名容器残留 |
执行 docker rm -f mosquitto 强制删除旧容器,再重新 docker compose up -d |