docker compose 启动 mongodb 副本集需五要素齐备:统一 hostname 与自定义网络、--replset 参数、healthcheck 确保服务就绪、entrypoint 控制 rs.initiate() 仅由首节点执行、keyfile 严格 400 权限及 uid 999 属主。

docker-compose 启动三个容器 ≠ 副本集
直接写三个 mongo 服务、暴露端口、挂载数据卷,启动后仍是孤立节点。执行 rs.status() 会报错 NoReplicationEnabled。副本集不是靠数量自动形成的,必须显式初始化,且所有节点要能通过可解析的主机名互相通信。
- 每个容器必须设固定
hostname(如mongo1),不能用默认随机名 - 所有容器必须在同一个自定义 Docker 网络里,才能用
hostname:27017互访 -
mongod启动时必须带--replSet rs0(名称统一、大小写敏感) -
rs.initiate()只能在主节点执行一次,且必须等全部节点 ready 后再操作
healthcheck 和 entrypoint 是初始化成败的关键
别依赖 depends_on——它只判断容器是否启动,不保证 mongod 已监听端口并接受命令。必须用 healthcheck 检查 MongoDB 实际可用性,并用自定义 entrypoint 控制初始化时机。
-
healthcheck推荐用:mongosh --eval "db.runCommand({ping:1})" -
entrypoint脚本需包含三步:启动mongod→ 等其他节点健康 → 判断自身是否为mongo1→ 执行rs.initiate()和rs.add() - 避免重复初始化:用环境变量或
hostname判断,只让一个节点执行初始化 - 成员地址必须写容器内可解析名,例如
{_id: 0, host: "mongo1:27017"},不能写127.0.0.1或宿主机 IP
密钥文件和权限容易被忽略
开启副本集认证(生产必需)时,keyFile 不只是生成就行,权限和属主出错会导致 mongod 拒绝启动。
- 生成命令必须是:
openssl rand -base64 756 > mongodb.key - 权限必须是
400:chmod 400 mongodb.key - 属主必须是 UID/GID 999:
chown 999:999 mongodb.key(MongoDB 容器默认用户) - 挂载路径需一致,且在所有节点上内容完全相同
- 启动参数要加
--keyFile /etc/mongo/mongodb.key --auth
连接字符串和客户端配置有坑
应用连接副本集时,如果用错地址或没配选项,会连不上主节点或无法故障转移。
- 连接串必须包含全部成员,例如:
mongodb://mongo1:27017,mongo2:27017,mongo3:27017/?replicaSet=rs0 - 不能只写一个节点——那样就退化成单点连接,失去副本集语义
- 务必加上
replicaSet=rs0查询参数,否则驱动不会启用副本集逻辑 - 事务要求所有节点使用相同 MongoDB 主版本(如全用
mongo:7.0),混合版本会失败
rs.status() 显示不全、主从不同步、或事务报错 Transaction numbers are not supported。











