假设ECS测试机上的一个容器不断显示Restarting,页面时好时坏。此时先删容器、重新拉镜像再启动,可能让服务暂时恢复,也可能把原容器的状态和日志入口一起丢掉。
我会先固定容器ID,保存退出状态和一段有时间边界的日志,再决定查配置、内存还是外部终止。退出码提供线索,不能单独充当故障结论。 本文按Docker官方资料整理,未在ECS实例运行,以下命令和分支均不是本次实测结果。
一、保留原容器,采一份当前快照
先确认Docker上下文指向目标主机,再列出全部容器;只看默认的运行列表,可能错过已经退出的对象。
docker ps -a --no-trunc
从列表复制目标容器的完整ID,替换下面的中文占位值。后续坚持用这个ID,避免同名服务重建后检查了新容器。选择有写权限的工作目录,在同一个终端执行:
umask 077
container_id='替换为目标容器完整ID'
evidence_dir=$(mktemp -d ./docker-evidence.XXXXXX) || exit 1
snapshot_end=$(date +%s)
window_start=$((snapshot_end - 1800))
printf 'container=%s\ncaptured_at_epoch=%s\n' \
"$container_id" "$snapshot_end" > "$evidence_dir/context.txt"
docker inspect --type container "$container_id" \
> "$evidence_dir/inspect.json" \
2> "$evidence_dir/inspect-error.txt"
docker logs --since "$window_start" --until "$snapshot_end" \
--tail 200 --timestamps "$container_id" \
> "$evidence_dir/logs.txt" 2>&1
每次采集新建一个目录,不覆盖前一次。这里保留采集起点的Unix秒时间戳,日志窗口固定为此前30分钟、最多末尾200行;没有使用持续跟随的-f。检查错误文件和日志内容,不能把命令报错生成的空文件算作证据采集成功。
inspect.json包含配置、挂载及可能存在的敏感环境变量,分享前脱敏。排查时先提取这些字段:
| 字段 | 先看什么 |
|---|---|
State.Status、State.ExitCode |
采集时状态与退出码,结合时间解释 |
State.OOMKilled |
当前状态中是否记录OOM终止 |
State.Error |
Docker记录的启停等错误,不等于应用完整报错 |
State.StartedAt、State.FinishedAt |
最近的启动、结束时间 |
RestartCount |
当前容器的重启计数线索 |
HostConfig.RestartPolicy |
是什么策略把退出后的容器再次拉起 |
这些字段不是每一轮退出的历史表。快速重启会更新状态;再次进入运行状态时,退出码和OOM标记还可能重置。连续命令也不是同一瞬间的原子快照,不能把采到的0或false当成此前从未失败的证明。

二、把137与OOM分开判断
137常见于按128+信号编号表示的SIGKILL退出。手工终止、停止超时后的强制结束等情况也可能出现;程序也可能自行返回这个数。看到137,不能直接写成“内存不足”。
继续取同一容器、同一时间窗口内的事件:
docker events --since "$window_start" --until "$snapshot_end" \
--filter "container=$container_id" --format '{
{json .}}' \
> "$evidence_dir/events.jsonl" \
2> "$evidence_dir/events-error.txt"
将oom、kill、die、start等事件与日志时间对齐。Docker历史事件只保留最近256条,节点繁忙时可能已经滚出窗口;没有查到oom,不等于没有发生过。
若OOM标记或事件支持内存方向,再核对该时段主机内核OOM记录、容器内存限制、内存监控与其他进程占用。应用日志也可能只来得及输出一半。主机当前内存充足或重启后占用很低,不能替代故障时刻的证据;尚未交叉核实就先记“疑似”,不直接取消限制或关闭OOM保护。
三、让下一步动作对应证据
| 当前线索 | 下一步检查 |
|---|---|
| 非零退出,日志稳定出现同一配置错误 | 核配置文件、变量、挂载路径及权限,只改命中的一项 |
State.Error有运行时启停错误 |
对照Docker守护进程日志和实际挂载、可执行文件等条件 |
| 137,但OOM证据不足 | 查操作记录、停止超时、外部管理器与同时间主机事件 |
| 退出码0,策略仍不断拉起 | 核启动命令是否本来就是一次性任务,主进程是否正常结束 |
| 日志为空或只有重复启动行 | 核日志驱动、轮转与应用是否写到容器内文件或外部后端 |
空日志不证明应用正常。docker logs主要读取标准输出、标准错误,是否有可用内容还取决于日志驱动和应用写入位置。
证据保存后,再安排必要的止损或维护动作。不要把无限restart当成修复,也不要先rm、down或清卷来消除现象。修正后沿同一套采集方法对比新旧ID、时间和日志,并验目标业务;短暂出现Up仍不足以验收。
四、独立练习与故障现场分开
如果只是练习识别日志和状态,可另选隔离测试环境,先准备固定版本的Nginx镜像:
docker pull docker.1ms.run/library/nginx:1.30.6-alpine
这是可选练习的预取步骤,本文未执行,也不要求在故障主机上拉取或替换业务镜像。拉取成功只说明镜像获取完成,不能解释已有容器为何退出。
交接时保留容器ID、采集时间、日志窗口、状态快照和待核假设。先让每个判断都能对应一份证据,再做下一次变更,才能区分服务恢复和原因查明。