在 Docker 环境中,容器因主机重启、Docker 服务重启或应用异常退出而停止,是运维过程中常见的问题。合理配置重启策略,可以提升服务可用性;但如果应用本身存在故障,自动重启也可能形成“启动—崩溃—再启动”的循环,掩盖真正原因。本文将从策略配置、状态判断到日志排查,系统介绍实用处理方法。🐳
一、认识 Docker 的四种重启策略
Docker 通过 --restart 参数控制容器退出后的行为,主要包含以下四种策略:
- no:默认策略,容器退出后不自动重启,适合临时任务、调试环境或一次性作业。
- on-failure:仅当容器主进程以非零状态码退出时重启,可通过“on-failure:次数”限制重试次数,适合允许失败重试但不应无限循环的程序。
- always:无论退出状态码是否为零,容器停止后都会被重新拉起。手动停止后暂时不会重启,但 Docker 守护进程再次启动时,容器仍可能自动运行。
- unless-stopped:行为与 always 接近,但会保留人工停止状态。若管理员主动停止容器,即使 Docker 服务或主机重启,它也不会自动启动。
上述行为可参考 Docker 官方重启策略文档。生产环境中的常驻服务通常可考虑 unless-stopped;批处理任务更适合 no 或 on-failure。不要为了“看起来稳定”而给所有容器统一设置 always。⚙️
二、配置和修改容器重启策略
1. 创建容器时指定策略
启动新容器时,可直接添加参数:
docker run -d --name web --restart unless-stopped nginx
如果服务异常退出后最多允许重试五次,可使用:
docker run -d --name worker --restart on-failure:5 my-worker-image
2. 修改已有容器的策略
无需删除或重新创建容器,可以通过 update 命令调整:
docker update --restart unless-stopped web
如需关闭自动重启,则执行:
docker update --restart no web
3. 在 Docker Compose 中配置
使用 Compose 管理服务时,可在对应服务下添加 restart 字段,例如:
services:
web:
image: nginx
restart: unless-stopped
修改配置后执行“docker compose up -d”,让声明式配置重新应用。应注意,普通 Compose 服务的 restart 字段与 Swarm 模式中的 deploy.restart_policy 并非完全相同,排查时要先确认当前使用的是单机 Compose 还是 Swarm 服务。
三、确认容器为何反复重启
发现容器状态不断显示 Restarting 时,不要立即删除重建。重建可能清除现场信息,也可能因配置未改变而再次失败。建议按以下顺序检查。🔍
- 查看运行状态:执行“docker ps -a”,确认容器状态、退出时间和端口信息。
- 查询退出码:执行“docker inspect 容器名”,重点关注 State、ExitCode、Error、OOMKilled、RestartCount 和 FinishedAt。
- 读取日志:执行“docker logs --tail 200 容器名”,必要时添加时间戳参数“--timestamps”。
- 检查启动配置:核对镜像、启动命令、环境变量、挂载目录、配置文件和依赖地址。
- 检查主机资源:确认内存、磁盘、inode、CPU 负载以及 Docker 数据目录是否异常。
常见退出码可作为线索,但不能孤立判断。退出码 0 通常表示主进程正常结束,如果配置了 always,原本只执行一次的脚本也会被持续拉起;退出码 1 多为应用通用错误;退出码 126 或 127 常与权限、命令不存在有关;退出码 137 常见于进程收到强制终止信号,也可能与内存不足有关。最终结论应结合容器日志、inspect 信息和主机系统日志确认。
四、高频故障原因与处理方法
应用启动后立即退出
Docker 容器是否存活取决于主进程。若启动脚本把服务放到后台后自行结束,容器会随之停止。应让应用以前台模式运行,并确保 ENTRYPOINT 或 CMD 指向真正需要长期运行的进程。
配置文件或环境变量错误
数据库地址写错、密钥缺失、配置格式不合法,都可能导致程序初始化失败。可使用“docker inspect 容器名”核对环境变量和挂载信息,同时检查宿主机文件是否存在、权限是否正确。敏感信息不宜直接复制到论坛或工单中。🔐
依赖服务尚未就绪
应用可能在数据库、缓存或消息队列可访问之前启动,连接失败后直接退出。可以增加合理的连接重试与退避机制,并通过 Compose 的健康检查和依赖条件改善启动顺序。但“先启动”不等于“已经可用”,应用自身仍应具备容错能力。
内存不足或资源限制过低
当 inspect 结果显示 OOMKilled 为 true,或主机日志出现内存不足记录时,应检查容器限制和应用实际消耗。处理方式包括优化程序内存、修复泄漏、调整并发量,或在主机容量允许的前提下合理提高限制,而不是只增加重启次数。
挂载目录权限不匹配
容器以非 root 用户运行时,可能无法读取配置或写入数据目录。应检查宿主机目录的所有者、权限及安全模块策略。不要直接使用过度宽松的权限作为长期方案,以免引入安全风险。
五、推荐的止损与排查流程
如果重启循环已影响主机负载,可先执行“docker update --restart no 容器名”取消自动重启,再执行“docker stop 容器名”停止服务。随后保存日志和 inspect 输出,核对最近的镜像、配置、依赖或资源变更。在测试环境验证修复后,再恢复合适的重启策略。🚑
对于重要服务,还应配置日志轮转、资源监控、退出码告警和重启次数告警。健康检查能够反映应用是否可用,但容器变为 unhealthy 并不必然触发普通 Docker 重启策略;如果需要自动处置健康异常,应结合应用自愈、编排平台或监控系统设计完整方案。
总结
Docker 重启策略解决的是“容器退出后是否再次启动”,不能替代应用稳定性治理。配置时应根据常驻服务、批处理任务和维护需求选择 no、on-failure、always 或 unless-stopped;遇到反复重启时,则应围绕退出码、容器日志、启动命令、依赖状态、目录权限及主机资源逐层排查。先保留现场、再定位根因,最后恢复策略,才能避免自动重启把真实故障变成难以察觉的循环。✅