on-failure策略仅在容器以非零退出码(如1、137)终止时触发重启,最多重试max_attempts次;exit 0不重启,OOMKilled(137)默认响应,需配合max_attempts防无限重启。
直接在本地构造几种典型崩溃行为,配合 docker inspect 和 docker logs 观察容器状态变化与重启动作是否符合预期,是最可靠、最轻量的测试方式。
模拟非零退出码崩溃(on-failure 策略核心场景)
这是 on-failure 策略唯一响应的场景。用一个简单镜像主动退出非零码:
- 运行命令:
docker run --restart=on-failure:3 alpine sh -c "echo 'crashing'; exit 1" - 容器会立即退出,状态变为
Exited (1),Docker 守护进程会在几秒内启动第 2 次 - 执行
docker ps -a查看重启次数(RESTARTS 列),连续失败 3 次后应停止尝试 - 对比
exit 0:若改为exit 0,即使配置了on-failure,也不会重启
模拟 OOM 被杀(退出码 137)
内存超限是生产中最常见的“静默崩溃”,但需注意:on-failure 默认响应 137,always/unless-stopped 也响应:
- 启动内存受限容器:
docker run --memory=50m --restart=on-failure:2 alpine sh -c "dd if=/dev/zero of=/dev/null bs=1M" - 观察
docker ps -a中退出码是否为137,RESTARTS 是否递增 - 用
docker inspect <id> --format='{{.State.OOMKilled}}'确认是否被 OOM Killer 终止 - 若希望避免无限重启(如数据库OOM后反复崩溃),建议加
:max-retries限制
验证 always/unless-stopped 对正常退出(0)的响应
区分这两者的关键在于“手动停止”行为:
- 先用
--restart=always启动一个容器,然后docker stop它 → 它不会自动重启 - 再用
--restart=unless-stopped启动,同样docker stop→ 它也不会重启(和 always 表现一致) - 关键区别在宿主机重启后:
always容器随 Docker 启动即拉起;unless-stopped容器只有在上次是docker stop停止时才不拉起,若上次是崩溃退出,则仍会拉起 - 测试方法:
sudo reboot后检查docker ps,两者都应运行;再docker stop+ 重启,此时unless-stopped不启动,always仍启动
结合 HEALTHCHECK 测试“假存活”场景
当应用进程还在,但业务已卡死(如 HTTP 服务无响应),仅靠进程存在无法触发恢复:
- 构建带健康检查的镜像(或用现成 nginx):
HEALTHCHECK --interval=10s --retries=2 CMD curl -f http://localhost/health || exit 1 - 启动时配
--restart=on-failure:docker run -d --restart=on-failure --health-cmd="curl -f http://localhost:80/health || exit 1" nginx - 进入容器停掉健康端点:
docker exec -it <id> sh -c "echo 'down' > /usr/share/nginx/html/health" - 等待约 20 秒(2×10s),
docker ps显示状态变为unhealthy,随后因健康检查失败退出并触发重启


















