docker四种重启策略行为边界明确:no完全不重启;on-failure仅响应非零退出码且可限次;always无视状态强制重启;unless-stopped尊重手动stop指令,宿主机重启后自动恢复。
选对重启策略不是加个参数就完事,关键得匹配服务类型、故障特征和运维意图。盲目用 always 可能掩盖真实问题,死循环重启;全用 no 又会让关键服务一崩就挂半天。
四种重启策略的真实行为边界
它们的触发逻辑有细微但关键的差别:
- no:容器退出后彻底静默,哪怕宿主机重启,它也不会起来——适合数据迁移脚本、单次ETL任务
- on-failure[:N]:只响应非零退出码(如1、137、143),但不响应 125/126/127这类 Docker 自身错误码;设了 N 就真只试 N 次,之后停住,方便人工介入
-
always:只要 Docker daemon 活着,容器退出就拉起——包括你手动
docker stop后,只要 daemon 重启,它又会自己跑起来 -
unless-stopped:唯一尊重“人工停止”意图的策略;
docker stop之后它真就停着,但宿主机重启、daemon 崩溃恢复后,它自动回归运行态
高并发场景下的策略组合建议
单靠 restart 不足以扛住流量洪峰或级联故障,需和健康检查、资源限制联动:
- Web/API 服务推荐 unless-stopped + HEALTHCHECK:每10秒探测
/health,连续失败3次才标记 unhealthy,再由 restart 策略触发重建 - 消息消费者(如 Kafka worker)用 on-failure:3:避免因临时网络抖动反复拉起,3次失败后停住,交由监控告警+人工排查消费位点异常
- 数据库容器(PostgreSQL/MySQL)慎用 always:应配 unless-stopped + 显式内存限制(
--memory=2g)+ 启动探针(start_period给够初始化时间),防止 OOM 后无限重启损坏数据文件 - 批处理任务(如定时导出报表)固定用 on-failure:1:失败一次就停,避免重复生成相同文件或双写数据
线上踩过的坑与规避方法
这些细节不注意,策略反而变成故障放大器:
-
重启风暴:应用启动即报错退出 → Docker 立刻重试 → 又报错 → 循环。解决办法是加
--restart=on-failure:3+HEALTHCHECK --start-period=60s,给足冷启动窗口 -
依赖未就绪就启动:比如 App 容器比 DB 容器先起来,连不上就崩溃退出。Docker Compose 里不能只靠
depends_on,要配合自定义健康检查脚本或 wait-for-it 工具 -
日志撑爆磁盘:容器高频重启时,日志持续写入,
docker logs查不到旧记录。必须配置日志驱动:--log-driver=json-file --log-opt max-size=10m --log-opt max-file=3 - 误判正常退出:有些工具(如 cron wrapper)成功执行完也返回非零码。这时不能用 on-failure,得改程序或用 no + 外部调度器控制
进阶:从单机策略走向集群自愈
当业务规模扩大,单机 restart 已不够用:
- Docker Swarm 中,把服务设为
replicas: 3+restart_policy: on-failure,节点宕机时任务自动漂移到其他节点 - Kubernetes 场景下,
restartPolicy: Always是 Pod 级别默认值,但真正容灾靠的是Deployment控制器维持副本数,配合 liveness/readiness 探针做精准剔除 - 生产环境建议:核心服务用 unless-stopped,搭配 Prometheus 监控容器退出事件(
container_last_seen{container!=""}下降)、告警通知 + 自动诊断脚本(检查端口、磁盘、连接池)











