《ESP32 物联网全栈实战-06》搭建 MQTT Broker
·
第 6 篇:数据上云——Docker 部署 MQTT Broker + 时序数据库 + Grafana
前 5 篇我们搞定了 ESP32 的传感器采集、WiFi 联网和 MQTT 上报。数据发出来了,存哪?怎么看?这篇带你用 Docker 一键部署完整的云端基础设施。
1. 整体架构
ESP32 → MQTT(tcp) → EMQX Broker → Telegraf → InfluxDB → Grafana
↑ │
手机/小程序 历史查询
(WebSocket)
四个组件的分工:
| 组件 | 作用 | 端口 |
|---|---|---|
| EMQX | MQTT Broker,接收设备消息,转发给订阅者 | 1883(MQTT), 18083(管理), 8084(WS) |
| Telegraf | 数据管道,从 MQTT 订阅 → 写入 InfluxDB | - |
| InfluxDB | 时序数据库,专门存带时间戳的数据 | 8086 |
| Grafana | 可视化仪表盘,折线图/柱状图/告警 | 3000 |
如果你不想折腾,用 EMQX Cloud 免费版也行(支持 5 个设备),省去自建 Broker 的麻烦。但学会自建是硬通货——面试和项目都用得上。
2. Docker 环境准备
在你的服务器或开发电脑上安装 Docker(Windows 用 Docker Desktop,Linux 用 apt/yum)。确认安装成功:
docker --version
docker compose version
3. 一键部署:docker-compose.yml
在项目根目录创建 docker-compose.yml:
version: '3.8'
services:
# === MQTT Broker ===
emqx:
image: emqx/emqx:5.7.0
container_name: emqx
ports:
- "1883:1883" # MQTT TCP
- "8083:8083" # MQTT WebSocket
- "8084:8084" # MQTT WSS (加密)
- "18083:18083" # Dashboard 管理后台
environment:
- EMQX_NAME=iot-broker
- EMQX_HOST=127.0.0.1
volumes:
- emqx_data:/opt/emqx/data
- emqx_log:/opt/emqx/log
restart: unless-stopped
# === 时序数据库 ===
influxdb:
image: influxdb:2.7
container_name: influxdb
ports:
- "8086:8086"
environment:
- DOCKER_INFLUXDB_INIT_MODE=setup
- DOCKER_INFLUXDB_INIT_USERNAME=admin
- DOCKER_INFLUXDB_INIT_PASSWORD=admin123456
- DOCKER_INFLUXDB_INIT_ORG=iot-org
- DOCKER_INFLUXDB_INIT_BUCKET=sensor-data
- DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=my-super-secret-token
volumes:
- influxdb_data:/var/lib/influxdb2
restart: unless-stopped
# === 数据管道 ===
telegraf:
image: telegraf:1.28
container_name: telegraf
volumes:
- ./telegraf.conf:/etc/telegraf/telegraf.conf:ro
depends_on:
- emqx
- influxdb
restart: unless-stopped
# === 可视化仪表盘 ===
grafana:
image: grafana/grafana:10.2
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin123
volumes:
- grafana_data:/var/lib/grafana
restart: unless-stopped
volumes:
emqx_data:
emqx_log:
influxdb_data:
grafana_data:
4. Telegraf 配置
创建 telegraf.conf(和 docker-compose.yml 同目录):
# MQTT 输入:订阅所有传感器数据
[[inputs.mqtt_consumer]]
servers = ["tcp://emqx:1883"]
topics = ["sensor/#"]
data_format = "json"
client_id = "telegraf-consumer"
# 写入 InfluxDB
[[outputs.influxdb_v2]]
urls = ["http://influxdb:8086"]
token = "my-super-secret-token"
organization = "iot-org"
bucket = "sensor-data"
关键细节:sensor/# 中的 # 是 MQTT 通配符,匹配所有以 sensor/ 开头的 topic。设备端上报 topic 设计成 sensor/device_id 即可全部被 Telegraf 捕获。
5. 启动与验证
# 启动所有服务
docker compose up -d
# 查看是否都跑起来了
docker compose ps
# 预期输出:4 个服务都是 Up 状态
验证各组件:
1. EMQX Dashboard: http://localhost:18083
用户名 admin,密码 public → 能看到设备连接数、消息吞吐量
2. InfluxDB: http://localhost:8086
用户名 admin,密码 admin123456 → Data Explorer 查询 sensor-data
3. Grafana: http://localhost:3000
用户名 admin,密码 admin123
→ 添加 InfluxDB 数据源 → 创建仪表盘
6. Grafana 创建温度仪表盘
步骤:
1. Connections → Data Sources → 添加 InfluxDB
- Query Language: Flux
- URL: http://influxdb:8086
- Organization: iot-org
- Token: my-super-secret-token
- Default Bucket: sensor-data
2. Dashboards → New → Add Visualization
- 数据源选 InfluxDB
- Flux 查询:
from(bucket: "sensor-data")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "mqtt_consumer")
|> filter(fn: (r) => r._field == "temp")
|> aggregateWindow(every: 10s, fn: mean)
- 图表类型选 Time series
- 标题:客厅温度
3. 同样方法添加湿度面板,收到同一个 Dashboard
效果:ESP32 每 5 秒发一次数据 → Grafana 自动实时刷新 → 还能设置告警(温度>35°C 发邮件/钉钉)。
7. ESP32 端的数据格式
为了让 Telegraf 能解析,MQTT 消息必须是 JSON 格式(因为上面配了 data_format = "json"):
// ESP32 上报的 payload 格式
char payload[128];
snprintf(payload, sizeof(payload),
"{"
"\"device\":\"livingroom_01\","
"\"temp\":%.1f,"
"\"humi\":%.1f,"
"\"rssi\":%d"
"}",
temperature, humidity, wifi_rssi);
esp_mqtt_client_publish(mqtt_client, "sensor/livingroom", payload, 0, 1, 0);
重要:JSON key(如 temp、humi)要和 Grafana 查询中的 _field 对应。
8. 安全提醒
上面为了方便用了简单密码。正式环境必须改:
- EMQX 开启用户名密码认证
- InfluxDB Token 用环境变量注入,不要写死在 yml 里
- Grafana 改默认密码
- 暴露到公网要加 Nginx 反向代理 + HTTPS
下一篇:BLE 蓝牙——当没有 WiFi 时,BLE 是你的通信方案
更多推荐


所有评论(0)