执行Entrypoint脚本后停止容器:MongoDB副本集配置容器终止方案
我之前也碰到过一模一样的场景——用临时容器跑副本集初始化脚本,完事就想让它自动退场,别占资源。下面是我实践下来最靠谱的几种方案,按优先级排序:
1. 让Entrypoint脚本自己优雅退出(核心方案)
Docker容器的生命周期完全绑定PID 1进程,只要这个进程正常退出,容器就会跟着停止。所以最简单的办法就是在你的配置脚本最后加上exit 0,确保脚本执行完所有初始化步骤后主动结束。
甚至可以在脚本开头加上set -eo pipefail,这样任何命令执行失败时脚本会立即退出,避免容器卡在“运行中”状态(比如MongoDB节点没就绪就执行初始化,脚本报错但还在跑)。
举个完整的脚本例子:
#!/bin/sh # 开启错误终止模式,任何命令失败立即退出 set -eo pipefail # 等待所有MongoDB节点就绪(关键步骤,不然初始化会失败) until mongosh --host mongo1:27017 --eval "db.adminCommand('ping')" >/dev/null 2>&1; do echo "等待mongo1就绪..." sleep 2 done until mongosh --host mongo2:27017 --eval "db.adminCommand('ping')" >/dev/null 2>&1; do echo "等待mongo2就绪..." sleep 2 done until mongosh --host mongo3:27017 --eval "db.adminCommand('ping')" >/dev/null 2>&1; do echo "等待mongo3就绪..." sleep 2 done # 执行副本集初始化 echo "开始初始化副本集..." mongosh --host mongo1:27017 --eval " rs.initiate({ _id: 'rs0', members: [ { _id: 0, host: 'mongo1:27017' }, { _id: 1, host: 'mongo2:27017' }, { _id: 2, host: 'mongo3:27017' } ] })" # 脚本执行完成,主动退出 echo "副本集初始化完成,容器即将停止" exit 0
2. 配合Docker Compose的--rm参数自动清理容器
启动配置容器时加上--rm,这样容器停止后会自动删除,不用你手动跑docker rm清理残留:
docker-compose up mongo-setup --rm
同时在你的docker-compose.yml里给这个配置服务加上restart: "no",防止容器意外重启(比如脚本出错退出后,Docker不会自动重启它):
services: mongo-setup: image: mongo entrypoint: ["/scripts/setup-replica.sh"] volumes: - ./scripts:/scripts # 挂载你的脚本目录 depends_on: - mongo1 - mongo2 - mongo3 restart: "no" # 禁止自动重启
3. 别用强制终止!
尽量避免用docker stop或者docker kill来终止容器——前者会发送SIGTERM信号等待进程退出,但如果脚本没处理信号可能还是会卡;后者是强制杀死进程,可能导致初始化步骤没执行完就中断。让脚本自己正常退出才是最优雅、最安全的方式。
额外小技巧
如果你的Docker Compose版本比较新(2.10+),可以给这个配置服务加上profiles: ["setup"],这样默认docker-compose up不会启动它,只有指定--profile setup才会运行:
services: mongo-setup: # ... 其他配置 ... profiles: ["setup"]
启动时就用:
docker-compose --profile setup up --rm
这样日常启动MongoDB集群时不会误启动这个临时容器,非常方便。
内容的提问来源于stack exchange,提问作者robert

