第 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(如 temphumi)要和 Grafana 查询中的 _field 对应。


8. 安全提醒

上面为了方便用了简单密码。正式环境必须改

  • EMQX 开启用户名密码认证
  • InfluxDB Token 用环境变量注入,不要写死在 yml 里
  • Grafana 改默认密码
  • 暴露到公网要加 Nginx 反向代理 + HTTPS

下一篇:BLE 蓝牙——当没有 WiFi 时,BLE 是你的通信方案

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐