必须使用3个Server节点以满足Raft多数派要求,通过固定IP或Docker DNS实现可靠节点发现,挂载独立数据卷保障状态持久化,并配置healthcheck与raft list-peers验证集群健康。

用 Docker 实现高可用 Consul 集群,核心是确保三个 Server 节点能稳定通信、自动选举 Leader、故障后自动恢复,并保留状态。关键不在“跑起来”,而在网络可控、数据不丢、启动顺序合理、节点可发现。
必须用 3 个 Server 节点,且全部启用 -server 模式
Consul 的 Raft 协议要求奇数个 Server 才能完成多数派(quorum)投票。3 节点集群可容忍 1 个节点宕机仍能正常写入和选举;2 节点无法达成多数,1 节点不具备容错能力。Client 节点可按需添加,但不参与 Raft 投票,只做服务注册/查询代理。
- 每个 Server 必须带 -server 参数启动
- 统一设置 -bootstrap-expect=3,表示集群期望有 3 个 Server 加入后才正式启动 Raft
- 避免混用 -bootstrap(仅用于单节点开发)和 -bootstrap-expect(生产集群必需)
固定网络 + 静态 IP 或可靠服务发现
容器重启或重建后 IP 会变,若靠动态 DNS 或容器名解析(如 consul-node2),可能因启动时序或 DNS 缓存导致 join 失败。推荐两种稳妥方式:
-
自定义 bridge 网络 + 静态 IPv4 地址:像 docker-compose 中定义
consul-net并为每个 service 分配固定 IP(如 172.20.0.11/12/13),所有-retry-join都指向这些地址 -
使用容器名 + Docker 内置 DNS:在同一个自定义网络中,容器可通过 service 名互相访问(如
consul-node2)。此时-retry-join=consul-node2可用,但需确保依赖顺序(如用depends_on+ healthcheck)
数据持久化与配置分离
Consul Server 的 Raft 日志、KV 数据、证书等默认存在内存或临时路径。容器一删,整个集群状态就清零,无法恢复——这直接破坏高可用前提。
- 为每个节点挂载独立的宿主机目录或命名卷:
-v ./data/node1:/consul/data - 不要共用同一目录,否则多个节点写入冲突
- 如需 ACL 或 TLS,把配置文件(JSON 或 HCL)放入挂载的
/consul/config目录,而非硬编码进 command
健康检查与可观测性不能少
集群“运行中”不等于“可用”。需确认 Leader 是否选出、各节点是否 Healthy、服务是否可注册查询。
- 启动后执行:
docker exec consul-node1 consul operator raft list-peers查看 Raft 成员列表及 Leader 标识 - 访问
http://localhost:8500/ui查 UI 中 Nodes 页面,确认 3 个 Server 状态均为 passing - 用
consul members命令验证 gossip 成员关系是否完整 - 建议在 compose 中加入
healthcheck,例如检测curl -f http://localhost:8500/v1/status/leader是否返回非空地址


















