服务器排障指南 · 更新于

Docker 容器一直重启怎么排查

刚把应用部署到 VPS,容器却一直显示 Restarting?重启策略只能重新拉起进程,不能修复根因。先找出进程为什么反复停下,再判断该改配置、查依赖还是处理资源不足。

1. 确认是重启循环,记下当前状态

docker ps -a --format 'table {{.Names}}\t{{.Status}}\t{{.Image}}'
docker inspect --format 'status={{.State.Status}} exit={{.State.ExitCode}} oom={{.State.OOMKilled}} finished={{.State.FinishedAt}} restarts={{.RestartCount}}' YOUR_CONTAINER
docker events --since 30m --until "$(date +%s)" --filter container=YOUR_CONTAINER --filter event=die --filter event=start

确认正在查看的是正确服务及镜像,记下故障时间和最近一次部署时间。每次执行 restarts 都在变大,或者 docker events 里 die / start 成对反复出现,就说明是重启循环。FinishedAt 是 UTC 时间。

一直重启时,括号里的数字去退出码指南查

括号里是上一次退出的退出码,只能帮你缩小下一步的范围。每个数字的完整含义和该跑的命令,见 Docker 退出码是什么意思?容器秒退、立即退出时看 0、1、125、137、139、143、255:

数字简要含义详细说明
0命令正常结束;服务可能把自己放到了后台#exit-code-0
1应用报错#exit-code-1
125 / 126 / 127Docker 没能运行 / 执行不了 / 找不到命令#exit-code-125、#exit-code-126、#exit-code-127
137SIGKILL;不能证明是内存不足#exit-code-137
139 / 143段错误 / 收到 SIGTERM 停止#exit-code-139、#exit-code-143

2. 查重启策略和 Docker 的退避间隔

docker inspect --format 'policy={{.HostConfig.RestartPolicy.Name}} max_retries={{.HostConfig.RestartPolicy.MaximumRetryCount}}' YOUR_CONTAINER
策略Docker 怎么做
no(默认)从不自动重启
on-failure[:N]只在非零退出后重启,可限制最多 N 次;次数用完后容器停在 Exited
always停了就重启;手动停止后,只有 daemon 或容器本身被重启时才会再拉起
unless-stopped和 always 类似,但你手动停掉的容器在 daemon 重启后也不会被拉起

每次重启前,Docker 会等得更久一点:间隔从 100 毫秒开始翻倍,最长 1 分钟;容器只要连续运行满 10 秒,间隔就重置。所以一个反复崩溃的容器会越来越长时间停在 Restarting,只短暂显示一下 Up。用 Compose 时,策略写在服务的 restart: 里。

改策略修不好失败的启动命令,只会改变你看到失败的频率。同一个容器不要同时用 Docker 重启策略和 systemd 这类宿主机进程管理器。详见 Docker 官方重启策略说明。

3. 只看故障附近的日志

docker logs --since 15m --tail 200 --timestamps YOUR_CONTAINER

从进程停下之前的第一条异常开始找,而不是只看最后一行;重启循环里同样的错误会反复出现。日志为空不代表没有故障:应用可能写到文件,或当前日志驱动无法提供这部分输出。此时检查应用的日志配置和服务启动记录。

4. 依赖还没就绪

很常见的一种循环:应用比数据库、缓存或某个 API 先起来,第一次连接失败就退出,然后被反复拉起,直到依赖碰巧就绪。

docker compose ps
docker compose logs --since 15m --timestamps YOUR_DEPENDENCY

5. 健康检查:它会重启什么、不会重启什么

docker inspect --format '{{json .State.Health}}' YOUR_CONTAINER

这条命令显示健康状态,以及最近几次检查的结果和输出。单机 Docker Engine 只会把容器标记为 unhealthy,不会因为健康检查失败去重启它。如果不健康的容器在被重启,说明是别的东西在做这件事(Swarm、编排工具或某个辅助容器),要去看那个工具的日志。

健康检查太严格,或者对启动慢的应用没设启动宽限期(start period),会让依赖它的服务一直卡在 service_healthy,或者让上面说的外部工具反复重启它。先看健康检查自己的输出,再怀疑应用。

6. 资源:内存、磁盘和端口

docker inspect --format 'memory_limit_bytes={{.HostConfig.Memory}}' YOUR_CONTAINER
docker stats --no-stream YOUR_CONTAINER
df -h

7. 把证据变成下一步,而不是立即执行建议

先记录“现象 → 证据 → 待验证原因 → 最小检查”。生产环境需要明确影响范围、维护窗口和回滚方式;不要把清理数据、删除容器或扩大权限当作通用修复。

在 OpsMate(itops.sh)里,可以给 AI 这样的任务:

每个处置按风险分三档:低风险的(比如有把握的服务重启、日志轮转)会直接自动执行;中风险的(比如改配置、重建容器)会先发给你审批,30 分钟内没人处理也会自动执行;高风险的(改数据库结构、内核参数、网络和防火墙)只告警、不执行。系统拿不准的时候,会按更高一档处理。未通过安全检查的命令会被拦截且不会执行。低风险修复默认自动执行,每一步都会记录。每次让 AI 帮忙看,终端里最近的输出都会一起发到云端 AI,敏感信息请先去掉。AI 的判断需要验证;它不能仅凭一段日志保证定位准确。

说明性示例:重启后数据库还没就绪

这是说明性示例,不是真实客户案例:宿主机重启后,应用容器显示 Restarting (1),重启次数不断上涨,而数据库容器是 Up。应用每次启动后的第一条日志都是连接数据库被拒绝,数据库日志显示那几个时间点它还在初始化。Compose 里只写了 depends_on,没有健康条件。这些证据支持“依赖没就绪”的判断。可选的改法是给数据库加健康检查并用 condition: service_healthy,或者在应用里加连接重试;这些都是要先确认的变更,改完再看重启次数是否停止增长。

根据证据选择下一步

常见问题

Docker 容器一直重启、反复显示 Restarting,是什么原因?

重启策略只能重新拉起进程,不能修复根因:容器一直重启,是主进程每次启动后又停下了。先确认是重启循环:每次执行 docker inspect,RestartCount 都在变大,或者 docker events 里 die / start 成对反复出现。再用 docker logs --since 15m --timestamps 找停下之前的第一条异常,常见原因有依赖没就绪、权限或文件问题、配置错误和资源不足。

为什么容器重启间隔越来越长,只偶尔显示一下 Up?

这是 Docker 的退避间隔:每次重启前的等待从 100 毫秒开始翻倍,最长 1 分钟;容器只要连续运行满 10 秒,间隔就重置。所以反复崩溃的容器会越来越长时间停在 Restarting。改重启策略修不好失败的启动命令,只会改变你看到失败的频率;同一个容器也不要同时用 Docker 重启策略和 systemd 这类宿主机进程管理器。

Compose 里写了 depends_on,应用还是因为数据库没起来反复重启?

单写 depends_on,只等依赖的容器启动,不等它就绪。condition: service_healthy 会等依赖的健康检查通过,前提是那个服务配了健康检查。如果应用连一次失败就退出,在应用里加一个简短的重试,通常比靠容器重启更合适。另外核对一下地址:容器里的 localhost 是容器自己,不是另一个服务。

健康检查显示 unhealthy,Docker 会自动重启这个容器吗?

单机 Docker Engine 不会。它只把容器标记为 unhealthy,不会因为健康检查失败去重启它。如果不健康的容器在被重启,说明是别的东西在做这件事(Swarm、编排工具或某个辅助容器),要去看那个工具的日志。用 docker inspect --format '{{json .State.Health}}' YOUR_CONTAINER 能看到最近几次检查的结果和输出,先看它,再怀疑应用。

查看全部排障指南

需要帮助理解排查结果?

OpsMate(itops.sh)把 SSH 终端和 AI 放在同一页,由你核对证据。每次让 AI 帮忙看,终端里最近的输出都会一起发到云端 AI,敏感信息请先去掉。

免费开始 本地凭证桌面端

继续查阅