Docker 容器重启策略 always on-failure 无重启怎么排查日志

文章导读
如果 Docker 容器配置了重启策略却没有自动重启,最常见的原因是退出码不符合策略要求,或者容器曾被手动停止。排查时应优先使用 docker inspect 查看状态码和重启计数。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 修改已存在容器的策略
  5. 怎么验证是否生效
  6. 常见坑
  7. 参考来源
A A

Docker 容器重启策略(always/on-failure)失效怎么排查日志

如果 Docker 容器配置了重启策略却没有自动重启,最常见的原因是退出码不符合策略要求,或者容器曾被手动停止。排查时应优先使用 docker inspect 查看状态码和重启计数。

先说结论:重启策略失效通常是因为退出码为 0 或容器被手动停止,需结合 inspect 状态和系统日志定位。

  • 先确认:检查容器退出码是否匹配 on-failure 策略
  • 先处理:查看 docker inspect 状态和重启计数
  • 再验证:通过测试容器验证策略是否生效
  • 补充:使用 docker update 修改运行中容器策略

命令速用版

# 查看容器退出码
docker inspect `--format`='{{.State.ExitCode}}' <容器 ID>

# 查看重启次数
docker inspect `--format`='{{.RestartCount}}' <容器 ID>

# 查看容器最后日志
docker logs `--tail` 100 <容器 ID>

# 查看 Docker 守护进程日志
journalctl -u docker.service `--since` "10 minutes ago"

为什么会这样

Docker 的重启策略行为取决于容器退出的原因和配置的策略类型。

  • on-failure:仅在容器以非零退出码(表示错误)退出时才会重启。如果容器正常退出(退出码 0),它不会重启。
  • always:会尝试始终重启容器,除非容器被手动停止(docker stop)。

此外,如果 Docker 守护进程本身重启或系统资源不足导致容器被杀死(如 OOM),日志可能未及时保存或策略未触发,这需要检查系统层面的日志。

分步处理

第一步:检查容器状态和退出码

使用 inspect 命令确认容器当前的状态和退出码。如果退出码是 0 且策略是 on-failure,不重启是符合预期的。

Docker 容器重启策略 always on-failure 无重启怎么排查日志
docker inspect <容器 ID> | grep -A 5 State

关注 ExitCodeRunning 字段。如果 Running 为 false 且 ExitCode 为 0,on-failure 策略不会触发。

第二步:检查重启计数

查看 RestartCount 字段。如果该数字为 0,说明容器启动后从未触发过重启策略。如果数字有增加但容器最终停止,可能达到了最大重试次数(如果配置了 on-failure:max-retries)。

第三步:检查系统日志

如果容器疑似被系统杀死(如 OOM),Docker 日志可能不完整。检查系统日志确认是否有 docker 守护进程重启或内核杀死进程的记录。

journalctl -u docker.service -n 50

如果是 Linux 系统,还可以检查 dmesg 是否有 OOMKilled 记录。

Docker 容器重启策略 always on-failure 无重启怎么排查日志

修改已存在容器的策略

如果容器已经运行但策略配置错误,无需删除容器,可使用 docker update 命令动态修改重启策略。

# 修改为始终重启
docker update `--restart`=always <容器 ID>

# 修改为失败重启,最多 3 次
docker update `--restart`=on-failure:3 <容器 ID>

# 禁用重启策略
docker update `--restart`=no <容器 ID>

注意:修改后需重启容器才能生效新策略(针对当前运行状态),但策略配置会持久化。

怎么验证是否生效

创建一个测试容器,分别验证退出码 0 和 1 的情况。

测试 on-failure 策略:

# 退出码 1,应该重启
docker run `--restart`=on-failure alpine exit 1

# 退出码 0,不应重启
docker run `--restart`=on-failure alpine exit 0

运行后观察 docker ps -a,第一个容器状态应变为 Restarting 或再次退出但重启计数增加,第二个容器应保持 Exited 且重启计数为 0。

常见坑

  • 日志轮转限制:如果配置了日志驱动的最大大小(max-size),旧日志可能被覆盖,导致看不到早期的报错信息。
  • 手动停止状态:如果容器曾被 docker stop 停止,即使策略是 always,Docker 也不会自动重启它,除非手动启动或 Docker 服务重启。
  • 依赖服务未就绪:容器启动后立即退出可能是因为依赖的数据库或网络未就绪,这种快速退出可能导致日志难以捕获,建议增加重试逻辑或健康检查。
  • 策略优先级:重启策略仅作用于容器本身,不保证容器间的启动顺序。若需依赖关系,请配合 depends_on 和健康检查使用。

参考来源

  • Docker Official Documentation, "Configure restart policies", https://docs.docker.com/config/containers/start-containers-automatically/