Docker的restart参数不支持按退出码差异化处理,仅提供no、on-failure、always、unless-stopped四种静态策略;其中on-failure对所有非零退出码一视同仁,无法区分1、137、143等具体含义,亦无钩子或条件表达式扩展能力。
docker 的 restart 策略本身**不支持根据容器退出码(如 1、137、143)差异化触发不同重启行为**。它只提供统一策略(no、on-failure、always、unless-stopped),其中 on-failure 虽可指定最大重试次数,但对所有非零退出码一视同仁,无法区分“该重试的错误”和“该停止的错误”。
为什么 Restart 参数无法按退出码差异化处理
Docker daemon 在容器退出后仅获取其退出状态码,但 restart 策略的判断逻辑是静态的:
-
on-failure[:max-retries]:只要退出码 ≠ 0 就尝试重启,不检查具体数值; - 退出码 1(应用内部错误)、137(OOM killed)、143(优雅终止)、255(无效参数)等,在 Docker 层面都被视为“失败”,无区别对待机制;
- Docker 不提供钩子、条件表达式或退出码匹配规则等扩展能力。
替代方案:用守护进程脚本封装容器启动
真正实现“按退出码决策”的核心思路是:**不让 Docker 直接管理重启,而是用外部脚本监听退出码并自主决定下一步动作**。
- 编写一个 shell 脚本(如
smart-runner.sh),内含docker run命令; - 脚本执行容器后,用
$?捕获退出码; - 根据预设规则判断:例如退出码 137 → 清理内存后重启;退出码 1 → 记录日志并退出;退出码 0 → 正常结束;
- 配合
while true循环 +sleep实现可控重启,避免高频拉起。
进阶实践:结合 healthcheck 与外部监控
若需更健壮的容错逻辑,可分层设计:
- 容器内启用
HEALTHCHECK,定期探测服务可用性(如 HTTP 200 或端口连通); - Docker 仅配置
--restart=on-failure作为兜底,防止进程崩溃; - docker inspect --format='{{.State.ExitCode}}' 获取历史退出码,并依据业务规则执行不同操作(告警 / 扩容 / 切流 / 人工介入);
- 关键错误(如数据库连接失败导致的退出码 1)可写入日志并触发 webhook,交由运维平台处理。
注意事项与常见误区
直接依赖 Docker 原生 restart 实现“智能重启”容易踩坑:
- 不要误以为
on-failure:3能跳过某些错误码——它只是最多重试 3 次,每次都会尝试; - OOM(137)通常需调整
-m内存限制或优化应用,而非盲目重启; - 频繁退出又重启可能掩盖真实问题(如配置错误、依赖缺失),应优先完善日志和可观测性;
- 使用脚本封装时,注意信号传递(如
docker run -it需处理 Ctrl+C)和资源清理(临时卷、网络)。


















