Docker容器重启策略有四种:no(默认,不自动重启)、on-failure[:N](仅非零退出码时重启,可限次)、always(任何停止都重启)、unless-stopped(除手动停止外均重启),选择依据是容器退出码而非直觉,且Kubernetes中该策略被忽略。
docker 容器重启策略不是“开了就行”的开关,而是服务可用性的第一道防线。配置不当,轻则反复重启打日志风暴,重则掩盖真实故障、拖垮宿主机资源。关键不在选哪个策略,而在于理解每个策略触发的条件、边界和副作用。
四种重启策略怎么选,看退出原因而非直觉
容器是否重启,只取决于它**怎么退出**,而不是“有没有挂”。Docker 不关心业务逻辑,只认 exit code 和 daemon 状态:
- no:默认策略。无论崩溃(exit 137)、OOM 被杀(exit 137)、还是正常结束(exit 0),都不重启。适合一次性任务或调试容器,保留现场供 inspect。
- on-failure[:N]:仅当容器以非零状态码退出时重启。加了 :5 就最多试 5 次,第 6 次失败后彻底停摆。适合有明确失败信号的服务(如数据库连接超时、配置加载失败),能防住瞬时错误,又不会无限兜底。
- always:只要容器停止(不管 exit code 是 0 还是 137),就立刻重启;连 Docker daemon 重启后也会自动拉起。适合无状态核心服务(如 Nginx、API 网关),但必须配合健康检查和启动延迟,否则可能陷入秒启秒崩循环。
- unless-stopped:和 always 类似,但会尊重你手动执行 docker stop 的意图——一旦你主动停掉,它就不会再自启。适合需要人工干预的后台服务(如定时任务调度器、数据同步组件)。
配置方式不止 run 命令,更新和编排都要覆盖
重启策略不是创建时写死就一劳永逸的,生产环境常需动态调整:
- 新建容器:
docker run --restart=on-failure:3 -d nginx:alpine - 更新已有容器(无需重建):
docker update --restart=unless-stopped container_id。注意:该命令不触发重启,只修改下次行为。 - Docker Compose 中设置:
restart: "on-failure:5"写在 service 下,支持 all、no、always、on-failure、unless-stopped 全部值。YAML 中记得加引号,避免 YAML 解析把 on-failure 当布尔值。
生产环境中最容易踩的三个坑
策略配对了,不代表高可用就稳了。这些细节没处理好,策略反而成隐患:
-
重启风暴:容器启动即报错退出 → 立刻重启 → 再报错 → 循环。解决方案是搭配
--restart=on-failure:3+ 应用层健康检查 + 启动失败后加 delay(例如在 entrypoint 脚本里 sleep 2)。 -
依赖顺序失效:A 服务设了 always,B 服务依赖 A 的数据库但没等 A ready 就启动,结果 A 还在初始化,B 已经连不上库崩溃退出。此时 B 的重启策略会不断拉起它,却始终连不上。必须用
depends_on+ 自定义健康检查,或改用 init 容器等待。 -
日志失控:容器高频重启时,
docker logs默认只显示最近一次启动的日志。若未启用日志驱动轮转(如json-file的max-size和max-file),宿主机磁盘可能被撑爆。务必在 daemon.json 或 run 命令中显式配置日志限制。
别和 Kubernetes 的 restartPolicy 混着用
如果容器跑在 K8s 里,Docker 层的重启策略基本无效。Kubernetes 的 kubelet 才是最终决策者,它会忽略容器自身的 --restart 设置,完全按 Pod 的 restartPolicy(Always / OnFailure / Never)控制生命周期。你在 Dockerfile 或 docker run 里写的重启策略,只会干扰本地开发调试,上线前必须清理或注释掉,避免造成认知混淆。



















