Docker容器启动后退出或反复重启怎么办

适用于已安装Docker Engine的Linux服务器。容器显示“Exited”或“Restarting”时,先确定是程序正常结束、应用报错,还是启动阶段就失败。下面的检查在Docker所在主机执行,需要已有Docker操作权限;所有命令都针对同一个容器。

1. 找到容器,保存状态和最近日志

docker ps -a --format 'table {{.ID}}\t{{.Names}}\t{{.Status}}'

-a会列出已停止的容器。找到故障容器的名称或ID,把下面的baoleyun-demo替换成实际值;后续命令在同一终端执行。

container_id='baoleyun-demo'
docker container inspect --format '状态={{.State.Status}}
退出码={{.State.ExitCode}} OOMKilled={{.State.OOMKilled}}
开始={{.State.StartedAt}}
结束={{.State.FinishedAt}}
重启次数={{.RestartCount}}
启动错误={{.State.Error}}
健康检查={{if .State.Health}}{{.State.Health.Status}}{{else}}暂无健康状态{{end}}' "$container_id"

docker logs --tail 200 --timestamps "$container_id"

先保存这些输出,再做重启操作。状态字段反映当前或最近一轮运行,持续重启时会变化。日志里的Z表示UTC时间,与北京时间相差8小时,核对故障时间时要统一。

日志为空也要继续查:应用可能写入自己的日志文件;远程日志驱动关闭本地缓存后,docker logs可能读不到内容。“暂无健康状态”可能是没有配置健康检查,也可能是容器尚未运行,不能据此判断应用健康。

2. 退出码只能缩小范围

看到的结果 下一步检查
Exited (0) 进程正常结束。备份、迁移等一次性任务可能已经完成;若它本应是常驻服务,检查启动脚本是否把服务放到后台后自行退出。先确认任务用途,避免重复执行已完成的业务操作。
Exited (1)等其他非零码 查看退出前的最后一段日志,优先处理缺少配置、连接依赖失败等明确错误。不同应用对退出码的定义不同。
Exited (137) 常见于收到SIGKILL。内存不足、人工强制停止、停止超时后被强制结束都可能出现137;需结合OOMKilled和同一时间的系统记录判断。
Exited (143) 通常与SIGTERM有关。先核对当时是否正在停止、部署或维护,不能直接认定为崩溃。
created,且“启动错误”有内容 从该错误入手,例如宿主机端口被占用、挂载路径不存在。应用可能根本没启动,因此未必有应用日志。

OOMKilled=true说明Docker记录到了OOM相关事件,应检查容器内存限制和服务器内存。false也不能单独排除更早发生的内存问题;对照故障时间查看系统日志,再按内存不足排查教程检查。

3. 按日志核对端口、挂载和依赖

下面只读取排查需要的配置字段,不输出整个容器配置:

docker container inspect --format '端口={{json .HostConfig.PortBindings}}
挂载={{json .Mounts}}
运行用户={{.Config.User}}
内存上限={{.HostConfig.Memory}}
重启策略={{json .HostConfig.RestartPolicy}}
日志驱动={{.HostConfig.LogConfig.Type}}' "$container_id"
日志或启动错误 具体处理方向
port is already allocated或绑定端口失败 核对输出中的HostPort,按端口监听检查方法找到占用者。确认用途后调整当前服务的端口映射;不要直接结束不明进程。
路径不存在、文件类型不符、Permission denied 核对挂载的Source(主机路径)与Destination(容器路径)、文件或目录类型,以及RW是否允许写入。按镜像要求核对运行UID/GID和目录权限。挂载覆盖镜像中的目录后,原有文件会被遮住;重装应用未必能解决路径配错。
数据库或其他依赖连接失败 检查依赖容器日志及就绪状态,再核对应用使用的地址、端口和账号。Compose的普通启动顺序不保证数据库已能接受连接;需要就绪等待的应用,应配置相应健康检查与service_healthy条件。

内存上限以字节计;该字段为0表示未单独设置硬上限,服务器实际内存仍然有限。重启策略也不会修复配置错误:on-failure只针对非零退出码,手动停止还会影响后续自动启动行为。单机Docker Engine的重启策略由进程退出触发,仅变为unhealthy不会触发该策略。

4. 修正后,只操作对应服务并复查

如果已修正挂载文件或外部依赖,确认该容器应长期运行且当前已停止,可启动这个容器,再重新读取第一步的状态和日志:

docker start "$container_id"

如果原来使用Compose部署,修改了环境变量、端口或挂载配置,单纯docker compose restart不会应用这些变更。先确认数据已有备份且保存在卷或挂载中、依赖服务已就绪。改卷名或挂载的Source/Destination不会自动迁移数据,重建前核对新配置仍指向需要保留的数据;容器可写层不能当作持久化备份。然后在原项目目录执行下列命令;把app替换为Compose中的服务名,并沿用原部署的-f、-p、--env-file等参数。

docker compose config --quiet && \
docker compose up -d --no-deps app

&&保证配置校验通过后才执行更新。后半条命令可能重建所选服务容器;若ID变了,重新从docker ps -a取得新ID,再设置container_id。不要把容器ID填在Compose服务名的位置。

复查应覆盖原来的故障周期:例如此前每隔10分钟退出一次,启动后只观察几十秒不够。确认同一容器的启动时间稳定、重启计数不再增加、日志没有重复原错误,并完成一次实际业务访问。重建后计数归零、本来没有健康检查、暂时显示“Up”,都不足以单独判断修复成功。

仍无法定位时,提交故障发生时间、容器状态和对应日志片段。按日志脱敏方法去掉密码、令牌与个人信息,不要直接公开完整docker inspect或.env文件。

依据:Docker官方容器状态、日志、存储、重启策略及Compose文档;核对日期:2026年11月4日。