【实战记录】Docker Compose 单机部署 EMQX 3 节点集群(5.8.8 社区版)完整踩坑与解决方案

一、背景与目标

在做 MQTT 架构 PoC / 技术验证 时,常见需求包括:

  • 同一台服务器 上部署 EMQX 集群

  • 使用 Docker Compose

  • 不使用企业版、不引入 License

  • 验证:

    • 集群可用性
    • 后续 TLS / 认证 / Topic 设计

本文记录一次 完整、真实的实战过程 ,以及最终稳定可复现的解决方案


二、结论先行(重要)

如果你不使用企业版、不配置 License,又需要多节点集群:

请使用 EMQX 5.8.x(如 5.8.8)

不要使用 5.9.0 及以上版本

原因见下文 License 章节。


三、核心问题与踩坑总结

1️⃣ EMQX 5.9.0+ 的 License 行为变化(关键)

EMQX v5.9.0 开始

  • EMQX 切换到 BSL 1.1(商业源许可证)
  • 即使使用 emqx/emqx(社区镜像)
  • 在技术层面限制多节点启动

当你尝试多节点集群时,日志会直接报错并退出:

text 复制代码
SINGLE_NODE_LICENSE,
make sure this node and peer nodes are configured with a valid license

📌 结论

版本 是否可无 License 集群
5.8.x ✅ 可以
5.9.0+ ❌ 不可以

2️⃣ Docker + Erlang 集群的经典大坑

EMQX 集群底层是 Erlang 分布式系统,对节点名要求非常严格:

❌ 常见错误方式
  • 使用 hostname
  • 使用 Docker DNS alias
  • 使用宿主机 IP
  • 使用 FQDN / 不一致的 host

这些都会导致典型错误:

text 复制代码
Node emqx1@xxx not responding to pings

甚至连:

bash 复制代码
emqx eval 'node().'

都会失败。


3️⃣ 正确、稳定、最少踩坑的方式(结论)

在 Docker Compose 同机部署场景中:

✅ 使用 Docker 内部固定 IP

❌ 不依赖 hostname / DNS

这是最稳妥、最容易复现的方案。


四、最终方案设计

技术选型

  • EMQX:5.8.8
  • 部署方式:Docker Compose
  • 节点数:3
  • 网络:Docker bridge + 固定 IP
  • 数据:本地目录持久化

五、最终目录结构

text 复制代码
.
├── docker-compose.yml
├── emqx1
│   ├── data
│   └── log
├── emqx2
│   ├── data
│   └── log
└── emqx3
    ├── data
    └── log

六、完整 docker-compose.yml(可直接使用)

yaml 复制代码
services:
  emqx1:
    image: emqx/emqx:5.8.8
    container_name: emqx1
    restart: unless-stopped
    networks:
      emqx-net:
        ipv4_address: 172.31.255.11
    environment:
      EMQX_NODE__NAME: emqx1@172.31.255.11
      EMQX_NODE__COOKIE: emqxclustersecret
      EMQX_CLUSTER__DISCOVERY_STRATEGY: static
      EMQX_CLUSTER__STATIC__SEEDS: emqx1@172.31.255.11,emqx2@172.31.255.12,emqx3@172.31.255.13
    volumes:
      - ./emqx1/data:/opt/emqx/data
      - ./emqx1/log:/opt/emqx/log
    ports:
      - "1883:1883"
      - "18083:18083"

  emqx2:
    image: emqx/emqx:5.8.8
    container_name: emqx2
    restart: unless-stopped
    networks:
      emqx-net:
        ipv4_address: 172.31.255.12
    environment:
      EMQX_NODE__NAME: emqx2@172.31.255.12
      EMQX_NODE__COOKIE: emqxclustersecret
      EMQX_CLUSTER__DISCOVERY_STRATEGY: static
      EMQX_CLUSTER__STATIC__SEEDS: emqx1@172.31.255.11,emqx2@172.31.255.12,emqx3@172.31.255.13
    volumes:
      - ./emqx2/data:/opt/emqx/data
      - ./emqx2/log:/opt/emqx/log

  emqx3:
    image: emqx/emqx:5.8.8
    container_name: emqx3
    restart: unless-stopped
    networks:
      emqx-net:
        ipv4_address: 172.31.255.13
    environment:
      EMQX_NODE__NAME: emqx3@172.31.255.13
      EMQX_NODE__COOKIE: emqxclustersecret
      EMQX_CLUSTER__DISCOVERY_STRATEGY: static
      EMQX_CLUSTER__STATIC__SEEDS: emqx1@172.31.255.11,emqx2@172.31.255.12,emqx3@172.31.255.13
    volumes:
      - ./emqx3/data:/opt/emqx/data
      - ./emqx3/log:/opt/emqx/log

networks:
  emqx-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.31.255.0/24

七、启动步骤(严格按顺序)

bash 复制代码
# 创建目录
mkdir -p emqx1/{data,log} emqx2/{data,log} emqx3/{data,log}
chmod -R 777 emqx1 emqx2 emqx3

# 停止旧容器
docker compose down

# 清空旧数据(避免 5.9.x 残留)
rm -rf emqx1/data/* emqx2/data/* emqx3/data/*

# 启动
docker compose up -d

八、验证步骤

1️⃣ 容器状态

bash 复制代码
docker ps | grep emqx

应看到 3 个 Up


2️⃣ Erlang 节点验证(关键)

bash 复制代码
docker exec -it emqx1 emqx eval 'node().'
docker exec -it emqx2 emqx eval 'node().'
docker exec -it emqx3 emqx eval 'node().'

输出示例:

text 复制代码
emqx1@172.31.255.11
emqx2@172.31.255.12
emqx3@172.31.255.13

3️⃣ 集群状态

bash 复制代码
docker exec -it emqx1 emqx ctl cluster status

期望结果:

text 复制代码
running_nodes =>
  emqx1@172.31.255.11
  emqx2@172.31.255.12
  emqx3@172.31.255.13

九、Dashboard 访问

text 复制代码
http://宿主机IP:18083

默认账号:

text 复制代码
admin / public

十、经验总结(非常重要)

✅ 推荐做法

  • 使用 EMQX 5.8.x
  • Docker 内部 IP 做节点名
  • 显式指定 Erlang Cookie
  • 清理 data 再切版本

❌ 不推荐做法

  • 5.9.0+ 社区版无 License 集群
  • 使用宿主机 IP 作为节点名
  • 使用 hostname / DNS alias
  • 版本切换不清 data

十一、下一步可做的事情

在此集群基础上,后续可以非常顺利地扩展:

  1. MQTT 双向 TLS(设备证书)
  2. HAProxy / Nginx MQTT 负载均衡
  3. EMQX 集群监控(Prometheus)
  4. 设备侧 Netty → MQTT 迁移

十二、结语

这次实践的最大价值不在于"搭起来了",而在于:

踩过了 EMQX + Docker + Erlang + License 的所有关键坑

后续无论是上云、上 K8s、还是切企业版,这套认知都会持续受用。

相关推荐
m0_738120725 小时前
Docker 环境下 Vulfocus 靶场搭建全流程(附镜像源问题解决方案)
运维·服务器·网络·安全·docker·容器
simeple5 小时前
记一次 Docker Compose 项目迁移:从 Windows Docker Desktop 迁移到 CentOS 服务器
docker
哆啦A梦——6 小时前
Ubuntu 虚拟机 Docker 与 MySQL 8.0.42 部署指南
mysql·ubuntu·docker
Plastic garden6 小时前
K8s知识(3) Pod亲和性,调度
云原生·容器·kubernetes
木雷坞7 小时前
Playwright MCP Docker 部署:mcr 镜像、浏览器工具和权限配置
运维·docker·容器·mcp
das2m7 小时前
WSL2 Ubuntu 配置完美版 docker compose 指南
linux·ubuntu·docker
暮云星影7 小时前
个人总结 docker搭建私人照片云相册Immich
docker·容器·arm
AI服务老曹7 小时前
破局异构计算与海量协议:基于 Docker 容器化的国标 GB28181/RTSP 边缘计算 AI 视频管理平台架构设计与源码交付实践
人工智能·docker·边缘计算
江湖有缘7 小时前
Docker一键部署open-resume简历生成器
运维·docker·容器