本教程将指导您通过Docker容器快速部署支持WebSocket和SSL加密的Mosquitto MQTT代理服务器,适用于物联网项目、智能家居等场景。
💡 非Debian系系统需调整安装命令
bash# 使用官方脚本安装
curl -fsSL https://get.docker.com | sh
# 验证安装
sudo docker run hello-world
bashmkdir -p mqtt5/{config,data,log} && cd mqtt5
mqtt5/ ├── config/ # 配置文件 ├── data/ # 持久化数据 └── log/ # 运行日志
config/mosquitto.conf
iniallow_anonymous true listener 1883 listener 9001 protocol websockets persistence true password_file /mosquitto/config/pwfile persistence_file mosquitto.db persistence_location /mosquitto/data/
1883 端口:适用于传统的 MQTT 客户端,使用标准的 MQTT 协议。
9001 端口:适用于 WebSocket 客户端,使用 MQTT over WebSocket 协议。
bashtouch config/pwfile
yamlversion: "3.7"
services:
# mqtt5 eclipse-mosquitto
mqtt5:
image: eclipse-mosquitto
container_name: mqtt5
ports:
- "9000:1883" #default mqtt port
- "9001:9001" #default mqtt port for websockets
volumes:
- ./config:/mosquitto/config:rw
- ./data:/mosquitto/data:rw
- ./log:/mosquitto/log:rw
restart: unless-stopped
# volumes for mapping data,config and log
volumes:
config:
data:
log:
networks:
default:
name: mqtt5-network
bashsudo docker-compose -p mqtt5 up -d
bash# 进入容器
sudo docker exec -it mqtt5 sh
# 创建用户(首次添加使用-c参数)
mosquitto_passwd -c /mosquitto/config/pwfile user1
# 添加更多用户
mosquitto_passwd /mosquitto/config/pwfile user2
# 删除用户
mosquitto_passwd -D /mosquitto/config/pwfile user2
下面是指令含义:
mosquitto_passwd is a tool for managing password files for mosquitto. Usage: mosquitto_passwd [-H sha512 | -H sha512-pbkdf2] [-c | -D] passwordfile username mosquitto_passwd [-H sha512 | -H sha512-pbkdf2] [-c] -b passwordfile username password mosquitto_passwd -U passwordfile -b : run in batch mode to allow passing passwords on the command line. -c : create a new password file. This will overwrite existing files. -D : delete the username rather than adding/updating its password. -H : specify the hashing algorithm. Defaults to sha512-pbkdf2, which is recommended. Mosquitto 1.6 and earlier defaulted to sha512. -U : update a plain text password file to use hashed passwords
重启docker容器让设置的用户生效:
sudo docker restart mqtt5
bashmkdir {caddy_data,caddy_config}
bash# 创建A记录指向服务器IP
mqtt.yourdomain.com A 123.45.67.89
在cf上这样:
vim Caddyfile
mqtt.dong-play.fun { reverse_proxy /ws/* http://mqtt5:9001 { # 确保 WebSocket 连接被正确处理 header_up X-Forwarded-Proto "https" header_up Host {host} header_up X-Real-IP {remote} header_up X-Forwarded-For {remote} } }
Caddy 被用作 Mosquitto Websocket 的反向代理,并自动为 mqtt.dong-play.fun 生成 SSL/TLS 证书。
yamlversion: "3.7"
services:
# mqtt5 eclipse-mosquitto
mqtt5:
image: eclipse-mosquitto
container_name: mqtt5
ports:
- "9000:1883" # default mqtt port
- "9001:9001" # default mqtt port for websockets
volumes:
- ./config:/mosquitto/config:rw
- ./data:/mosquitto/data:rw
- ./log:/mosquitto/log:rw
networks:
- caddy-mqtt
restart: unless-stopped
# caddy for HTTPS and reverse-proxy
caddy:
image: caddy:latest
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./caddy_data:/data
- ./caddy_config:/config
networks:
- caddy-mqtt
# volumes for mapping data,config and log
volumes:
config:
data:
log:
caddy_data:
caddy_config:
networks:
caddy-mqtt:
name: caddy-mqtt
# MQTT Connection URL would be # WSS => Websocket Secure with SSL wss://mqtt.dong-play.fun:443
安装客户端:
sudo apt install mosquitto-clients -y
bash# Without authentication 匿名访问,执行下面这句后会一直等待消息
mosquitto_sub -v -t 'hello/topic' -h localhost -p 9000
# With authentication
mosquitto_sub -v -t 'hello/topic' -u user1 -P <password> -h localhost -p 9000
# Alternate way in url format
# Format => mqtt(s)://[username[:password]@]host[:port]/topic
mosquitto_sub -v -L mqtt://user1:abc123@localhost/test/topic
bash# Without authentication匿名访问,执行下面这句后就是发布了消息,在订阅哪里会收到消息
mosquitto_pub -t 'hello/topic' -m 'hello MQTT' -h localhost -p 9000
# 用IP访问,在主题上发布消息
mosquitto_pub -t 'hello/topic' -m 'hello MQTT' -h 198.12.95.182 -p 9000
# 用域名访问,在主题上发布消息
# With authentication
mosquitto_pub -t 'hello/topic' -m 'hello MQTT' -u user1 -P <password>
# Alternate way in url format
# Format => mqtt(s)://[username[:password]@]host[:port]/topic
mosquitto_pub -L mqtt://user1:abc123@localhost/test/topic -m 'hello MQTT'
bashmosquitto_sub -L mqtts://user1:[email protected]/test/topic
bashsudo docker run -d --name mqttx-web -p 8080:80 emqx/mqttx-web
访问 http://localhost:8080
pip install paho-mqtt
ws服务:
import time import paho.mqtt.client as mqtt # 定义回调函数,当连接成功时调用 def on_connect(client, userdata, flags, rc): if rc == 0: print("连接成功!") # 订阅主题 client.subscribe("test/topic") else: print(f"连接失败,错误码:{rc}") # 定义回调函数,当收到消息时调用 def on_message(client, userdata, msg): print(f"收到消息: {msg.payload.decode()} 来自主题: {msg.topic}") # 创建 MQTT 客户端实例 client = mqtt.Client(transport="websockets") # 使用 WebSocket 传输 # 设置回调函数 client.on_connect = on_connect client.on_message = on_message # 连接到 Mosquitto 服务器 client.connect("198.12.95.182", 9001, 60) # 9001 是 WebSocket 端口 # 启动循环以保持连接 client.loop_start() # 发布消息 try: while True: client.publish("hello/topic", "Hello from Python over WebSocket!") print("消息已发布") time.sleep(2) # 每 2 秒发布一次消息 except KeyboardInterrupt: print("程序已停止") # 停止循环并断开连接 client.loop_stop() client.disconnect()
Q:为什么需要设置allow_anonymous为false?
A:出于安全考虑禁用匿名访问,必须通过用户名/密码认证
Q:如何查看容器日志?
bashsudo docker logs mqtt5 --tail 100
Q:SSL证书自动续期如何实现?
Caddy Server会自动处理Let's Encrypt证书的获取和续期
本文作者:Dong
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!