Docker容器自动终止问题求助:MongoDB副本集容器部署调试
用Docker Compose搭建MongoDB副本集(1主1从1仲裁)
我来帮你把这套MongoDB副本集的Docker配置梳理清楚,还会补充完整的docker-compose.yml文件,让你能快速搭建起测试环境:
1. 你的Dockerfile解析
先看你提供的Dockerfile,每一行的作用都很清晰:
FROM mongo:3.6.2 MAINTAINER Shanty RUN apt-get update && apt-get install -y netcat COPY ./.docker/mongo_scripts /mongo_scripts RUN chmod +rx /mongo_scripts/*.sh EXPOSE 27091 27092 27093 ENTRYPOINT ["/mongo_scripts/rs.sh"]
FROM mongo:3.6.2:基于官方稳定的MongoDB 3.6.2镜像作为基础RUN apt-get update && apt-get install -y netcat:安装netcat工具,用来检测MongoDB服务是否就绪,这对副本集初始化至关重要COPY ./.docker/mongo_scripts /mongo_scripts:把本地的初始化脚本目录复制到容器内RUN chmod +rx /mongo_scripts/*.sh:给脚本添加执行和读取权限,确保容器启动时能正常运行脚本EXPOSE 27091 27092 27093:暴露三个端口,对应副本集的主、从、仲裁节点ENTRYPOINT ["/mongo_scripts/rs.sh"]:指定容器启动时优先执行副本集初始化脚本
小建议:现在Docker官方更推荐用LABEL maintainer="Shanty"替代MAINTAINER指令,你可以根据需要调整。
2. 完善副本集初始化脚本(rs.sh)
你只写了脚本开头,我帮你补全完整的逻辑,确保副本集能正确初始化:
#!/bin/bash set -e # 等待MongoDB服务启动就绪的工具函数 wait_for_mongo() { local host=$1 local port=$2 echo "等待MongoDB服务在${host}:${port}就绪..." while ! nc -z "$host" "$port"; do sleep 1 done echo "MongoDB服务${host}:${port}已就绪" } # 根据节点角色启动对应配置的MongoDB服务 if [ "$NODE_ROLE" = "primary" ]; then # 启动主节点MongoDB,指定副本集名称和绑定所有IP mongod --port 27091 --dbpath /data/db --replSet rs0 --bind_ip_all & MONGO_PID=$! wait_for_mongo localhost 27091 # 初始化副本集配置 mongo --port 27091 <<EOF rs.initiate({ _id: "rs0", members: [ { _id: 0, host: "mongo-primary:27091" }, { _id: 1, host: "mongo-secondary:27092" }, { _id: 2, host: "mongo-arbiter:27093", arbiterOnly: true } ] }) EOF elif [ "$NODE_ROLE" = "secondary" ]; then # 启动从节点MongoDB,等待加入副本集 mongod --port 27092 --dbpath /data/db --replSet rs0 --bind_ip_all & MONGO_PID=$! wait_for_mongo localhost 27092 elif [ "$NODE_ROLE" = "arbiter" ]; then # 启动仲裁节点MongoDB,等待加入副本集 mongod --port 27093 --dbpath /data/db --replSet rs0 --bind_ip_all & MONGO_PID=$! wait_for_mongo localhost 27093 fi # 保持容器前台运行,避免启动后自动退出 wait $MONGO_PID
这个脚本的核心逻辑:
set -e:遇到错误立即退出,避免无效的后续操作wait_for_mongo:用netcat检测端口,确保MongoDB完全启动后再执行初始化- 根据
NODE_ROLE环境变量区分节点类型,主节点负责初始化副本集,从节点和仲裁节点只需要启动服务等待加入 - 最后用
wait $MONGO_PID让容器保持运行状态
3. 完整的docker-compose.yml配置
有了Dockerfile和脚本,还需要docker-compose.yml来编排三个节点:
version: '3.7' services: mongo-primary: build: . container_name: mongo-primary environment: - NODE_ROLE=primary ports: - "27091:27091" volumes: - primary-data:/data/db networks: - mongo-cluster mongo-secondary: build: . container_name: mongo-secondary environment: - NODE_ROLE=secondary ports: - "27092:27092" volumes: - secondary-data:/data/db networks: - mongo-cluster depends_on: - mongo-primary mongo-arbiter: build: . container_name: mongo-arbiter environment: - NODE_ROLE=arbiter ports: - "27093:27093" volumes: - arbiter-data:/data/db networks: - mongo-cluster depends_on: - mongo-primary volumes: primary-data: secondary-data: arbiter-data: networks: mongo-cluster: driver: bridge
配置说明:
- 三个服务分别对应主、从、仲裁节点,共用同一个Dockerfile构建镜像
- 通过
NODE_ROLE环境变量传递节点类型给初始化脚本 - 每个节点挂载独立的Docker卷,避免容器销毁后数据丢失
- 自定义
mongo-cluster网络,让节点之间可以通过容器名(如mongo-primary)直接通信 depends_on确保主节点先启动,但真正的服务就绪检测还是靠脚本里的wait_for_mongo
4. 启动和验证步骤
- 构建并启动所有容器:
docker-compose up -d --build
- 验证副本集状态:
进入主节点容器,连接MongoDB后查看状态:
docker exec -it mongo-primary mongo --port 27091 > rs.status()
你应该能看到三个节点都处于PRIMARY、SECONDARY、ARBITER的正常状态。
- 验证主从同步:
在主节点插入测试数据:
> db.test_collection.insert({name: "test_data"})
然后进入从节点容器,开启从节点查询权限后查看数据:
docker exec -it mongo-secondary mongo --port 27092 > rs.slaveOk() > db.test_collection.find()
能看到刚才插入的测试数据,就说明主从同步正常了。
内容的提问来源于stack exchange,提问作者Shubham Gupta
相关产品推荐
相关产品推荐

