直接用 docker-compose 启动三个 mongod 容器不等于副本集,因未执行 rs.initiate() 且节点间 hostname 不可达;必须配置 --replSet、固定 hostname、自定义网络、健康检查及 entrypoint 初始化脚本。
docker-compose 启动三个 mongod 容器不等于副本集常见错误是只写三个服务、暴露端口、挂载数据卷,但没触发初始化——容器起来后仍是独立节点,rs.status() 报错 NoReplicationEnabled。副本集不是靠“多个容器”自动形成的,必须显式执行 rs.initiate(),且所有节点需能通过彼此可解析的主机名通信。
mongo1、mongo2),不能依赖默认随机名localhost 或宿主机 IPmongod 启动时必须带 --replSet 参数,否则不接受副本集命令ready 状态)后再做docker-compose.yml 控制初始化顺序和时机官方镜像不内置初始化逻辑,得靠自定义 entrypoint 脚本配合健康检查来串起流程:先等所有 mongod 进程监听成功,再选一个节点执行 rs.initiate() 和 rs.add()。不能用 depends_on 简单等待,因为它只判断容器是否启动,不判断 MongoDB 是否 ready。
healthcheck:用 mongosh --eval "db.runCommand({ping:1})" 检查连通性entrypoint 覆盖默认启动命令,包装成“启动 mongod + 等待其他节点就绪 + 条件性执行初始化”三步mongo1 执行初始化(通过环境变量或主机名判断),避免重复调用导致 already initialized 错误mongo1:27017、mongo2:27017,而非 127.0.0.1
docker-compose.yml 关键配置项说明以下片段是可直接运行的核心部分,省略了完整文件结构,聚焦易错参数:
version: '3.8'services: mongo1: image: mongo:7.0 hostname: mongo1 command: mongod --replSet rs0 --bind_ip_all --port 27017 healthcheck: test: ["CMD", "mongosh", "--eval", "db.runCommand({ping:1})"] interval: 10s timeout: 5s retries: 5 environment: - MONGO_INITDB_ROOT_USERNAME=admin - MONGO_INITDB_ROOT_PASSWORD=pass volumes: - mongo1_data:/data/db<p>mongo2:image: mongo:7.0hostname: mongo2command: mongod --replSet rs0 --bind_ip_all --port 27017</p><h1>... 同样的 healthcheck、env、volumes 配置</h1><p>mongo3:image: mongo:7.0hostname: mongo3command: mongod --replSet rs0 --bind_ip_all --port 27017</p><h1>... 同样配置</h1><p>volumes:mongo1_data: {}mongo2_data: {}mongo3_data: {}</p>
--bind_ip_all 必须显式指定,否则默认只监听 127.0.0.1,容器间无法访问command 中加 --auth——它会阻止初始化阶段的无认证连接;等副本集建好再通过 db.createUser() 开启权限控制network_mode: "bridge" 并配 hosts(推荐前者)单独写一个 init-replica.sh 放进镜像或挂载为 volume,在 mongo1 的 entrypoint 中调用。核心是:等 mongo2 和 mongo3 健康后,用 mongosh 连自己执行初始化命令。
until 循环 + mongosh --eval 检查 mongo2 和 mongo3 是否响应,超时设为 60 秒较稳妥rs.initiate({ _id: "rs0", members: [{_id:0,host:"mongo1:27017"},{_id:1,host:"mongo2:27017"},{_id:2,host:"mongo3:27017"}] })
rs.initiate() 后立即调用 rs.conf() 查看配置,确认 members 数量和状态正确rs.add() 而非重新 rs.initiate(),后者会清空已有配置事务支持本身不需要额外配置,只要副本集状态正常、使用 majority 写关注,并在客户端开启 session 即可。最容易被忽略的是:初始化后没重启应用连接字符串——它仍连着单机地址,得改成 mongodb://mongo1:27017,mongo2:27017,mongo3:27017/?replicaSet=rs0。