容器重启策略需匹配服务性质,四种策略各适用不同场景:no适合调试和一次性脚本;on-failure响应非零退出码,宜设重试次数;always无条件重启但易引发“重启风暴”;unless-stopped为生产首选,支持手动停止且不自动恢复。
容器重启策略不是“开了就稳”,而是要匹配服务性质、退出行为和运维意图。选错策略可能掩盖故障,也可能让关键服务停摆。
四种策略到底怎么选
no:默认不重启,适合调试容器或一次性脚本。比如运行数据库迁移命令后正常退出(状态码0),你并不希望它反复重跑。
on-failure:只对非零退出码响应,最常用在批处理、后台任务中。加个重试次数更稳妥,例如 on-failure:3 —— 连续失败3次就停住,避免无限循环消耗资源。
always:不管退出码是0、1还是137(OOM被杀),一律重启。适合长期守护进程,但有个隐藏风险:如果程序本身有致命缺陷,它会不停拉起又崩溃,形成“重启风暴”。
unless-stopped:生产环境推荐首选。容器随 Docker daemon 启动而自启,也支持你手动 docker stop 临时下线,之后不会自动复活 —— 这点比 always 更可控。
配置方式要分场景
命令行启动时用 --restart 参数:
- docker run -d --restart=unless-stopped --name nginx nginx
- docker run -d --restart=on-failure:5 my-batch-job
Docker Compose 中直接写在 service 下:
services:
api:
image: my-api:v2
restart: unless-stopped
worker:
image: my-worker
restart: on-failure:3
已运行的容器不能直接改策略,需先 docker stop,再用 docker update --restart=xxx 容器名 更新,最后 docker start。
别忽略这些关键细节
退出码决定是否触发重启 —— 状态码0(成功退出)在 on-failure 下不会重启,但在 always 和 unless-stopped 下仍会重启。
125/126/127 这类 Docker 自身错误码,on-failure 不会重试,因为问题不在容器内,而在运行环境。
重启不是万能的:如果容器因内存超限被 OOM kill(退出码137),光靠重启没用,得配合 --memory 限制和健康检查一起用。
建议搭配健康检查使用,比如:
healthcheck: test: ["CMD", "curl", "-f", "http://localhost/health"] interval: 30s retries: 3
这样容器即使“活着”,但服务不可用,也会被标记为不健康并触发重启逻辑。
高可用不是单点靠重启
重启策略只是第一道防线。真正高可用需要三层配合:
- 容器层:用 unless-stopped + 健康检查,保证单实例快速恢复;
- 编排层:Docker Swarm 或 Kubernetes 控制副本数与跨节点调度,防止单机故障;
- 基础设施层:宿主机监控、日志集中收集、异常重启告警(比如1分钟内重启5次就发钉钉)。
没有健康检查的 always 是盲人骑马,没有多副本的 unless-stopped 是单点裸奔。











