容器"起不来、起来就崩、网络不通、拉不到镜像"——排障最怕乱试。Docker 排障有清晰的信息源:退出码、日志、事件、inspect、exec。本指南给出一套可复用的排障路径:先看"容器为什么退出"(退出码),再看"它说了什么"(日志),最后"进去看"(exec/调试),并覆盖 OOM、镜像、网络等高频问题。
关键概念:容器排障的信息金字塔——
docker ps -a(状态)→docker logs(它说了什么)→docker inspect(配置与挂载)→docker events(发生了什么)→docker exec(进现场)。按这个顺序,别先乱删重建。
1. 先定位:容器为什么退出
1.1 从状态看退出码
docker ps -a # 看所有容器状态
docker inspect -f '{{.State.ExitCode}} {{.State.Error}}' <container>
docker inspect -f '{{.State.Status}} {{.State.OOMKilled}}' <container>
常见退出码:
0 正常退出(任务型容器完成/主动 exit)
1 程序错误退出(应用自己 exit(1))
125 docker run 本身错误(参数/镜像不存在)
126 命令无法执行(文件不存在/无执行权限)
127 命令找不到(command not found)
128+ 被信号杀死(128 + 信号号)
137 = 128+9,SIGKILL → 常见 OOM 被内核杀掉
139 = 128+11,SIGSEGV 段错误
143 = 128+15,SIGTERM 正常终止
ℹ️ 核心:退出码是第一线索。137/OOMKilled=true → 内存问题;127 → 命令/路径问题;125 → 运行参数问题。先读码,再对症。
1.2 启动失败的常见原因
起不来(Restarting / Exited)的排查顺序:
1. 命令/ENTRYPOINT 不存在或拼错(exit 126/127)
2. 依赖服务没起来(数据库连接失败,看日志)
3. 挂载卷权限/路径错误
4. 端口占用(bind: address already in use)
5. 资源不足(内存不够 OOM)
6. 环境变量缺失/配置错误
2. 它说了什么:日志与事件
2.1 看日志
docker logs --tail 100 <container> # 最后 100 行
docker logs -f <container> # 实时跟随
docker logs --since 10m <container> # 最近 10 分钟
# 应用写 stdout/stderr 才会进 docker logs
# 写到文件/别处的日志要去容器里看或看挂载
2.2 看事件(了解发生了什么)
docker events --since 30m
# 输出:container create / start / die / oom / kill 等事件
# 只看某容器
docker events --filter container=<name>
events 的价值:
看 OOM、重启、kill 等"状态变迁",配合日志定位根因
比只看最终状态更能还原过程
3. 进去看:exec 与调试镜像
3.1 docker exec 进入运行容器
docker exec -it <container> bash # 交互式 shell
docker exec <container> ps aux # 执行任意命令
docker exec <container> cat /etc/nginx/nginx.conf
注意:
- exec 需要容器仍在运行
- 容器里可能没有 shell/调试工具 → 用调试镜像
- exec 是"进现场",别在 exec 里乱改(重启即失)
3.2 容器里没有工具怎么办
方案一:用调试镜像共享网络/命名空间
docker run -it --rm --network container:<target> \
--pid container:<target> \
nicolaka/netshoot bash
# netshoot 自带 curl/ss/tcpdump/dig 等排查工具
方案二:nsenter 从宿主机进入容器命名空间
pid=$(docker inspect -f '{{.State.Pid}}' <container>)
nsenter -t $pid -m -u -i -p bash
方案三:拷贝文件进去/出来
docker cp <container>:/etc/app/config.json ./config.json
docker cp ./fix.sh <container>:/tmp/
4. OOM 与资源问题
4.1 定位 OOM
# 确认是否被 OOM 杀掉
docker inspect -f '{{.State.OOMKilled}}' <container>
# 宿主机 OOM 记录(内核日志)
dmesg | grep -i "out of memory" | tail
journalctl -k | grep -i oom
OOM 两种:
容器被 cgroup 限额杀(内存超过 --memory)→ OOMKilled=true
宿主机整体内存不足 → 内核随机杀进程(可能杀到别容器)
→ 对症:前者调大容器 limit;后者给节点扩容/腾内存
4.2 资源排查
docker stats --no-stream # 看每个容器资源占用
# 确认:谁吃内存、谁打满 CPU
# 进程层面的容器内排查
docker exec <container> ps aux --sort=-%mem | head
资源问题的治理:
- 明确 limits(防止单容器拖垮)
- 定位是"业务峰值"还是"内存泄漏"(看是否持续增长)
- 泄漏 → 修代码/加 monitoring;峰值 → 容量规划
5. 镜像与构建问题
5.1 拉取失败
常见拉取失败:
- 网络问题 / 认证失败 / 权限不足
- 镜像不存在或 tag 拼错
- registry 无法访问(自建/内网代理)
排查:
docker pull 报错信息、检查 /etc/docker/daemon.json 的 registry-mirrors
docker login 检查认证
DNS / 代理 / 防火墙逐层看
5.2 构建失败
常见构建失败:
- 某 RUN 命令报错(网络下载失败、依赖装不上)
- 缓存问题(陈旧缓存导致行为异常)→ --no-cache 重试
- COPY 源文件不存在
- 资源不足(构建内存不足 OOM)
调试:
docker build --no-cache . # 绕开缓存
docker build --progress=plain . # 完整输出(不看省略)
docker build --target <stage> . # 只构建到某阶段
6. 网络与端口问题
常见网络排查:
- 端口不通:确认 -p 映射、容器内监听、防火墙
- 容器间不通:网络模式/自定义网络/DNS 解析
- 出网失败:DNS、代理、路由
工具链:
docker port <container> # 端口映射情况
docker exec <container> ss -tlnp # 容器内监听端口
docker exec <container> ping/dig/curl # 连通性
# 或用 netshoot 调试镜像(tcpdump/dig/curl 齐全)
# 快速验证端口映射
curl -v http://localhost:<published>/
# 不通时:看容器内是否真在监听 + 防火墙是否放行
7. 一套可复用的排障 SOP
标准排障路径(按顺序,不跳步):
1. docker ps -a —— 状态与退出码
2. docker logs --tail —— 应用说了什么
3. docker inspect —— 配置/挂载/环境
4. docker events —— 状态变迁/OOM/kill
5. docker stats —— 资源占用
6. docker exec —— 进现场(或 netshoot)
7. 定位根因 → 对症修复 → 记录复盘
快速定位口诀:
先看退出码,再读日志,进去看现场,最后查事件
避坑提醒:
- 别一上来就 docker rm -f 重建(丢失现场证据)
- 修复前先确认根因(改一行就能省去反复)
- 高发问题沉淀为 checklist/SOP
8. 常见避坑速查
| 现象 | 排查点 | 对策 |
|---|---|---|
| 退出码 137 | OOM | 调 limit / 定位泄漏 |
| 退出码 127 | 命令不存在 | 检查 ENTRYPOINT/路径 |
| 起不来 | 依赖没就绪 | 加 wait/healthcheck |
| 日志为空 | 应用写文件没写 stdout | 进容器/看挂载 |
| 网络不通 | 映射/监听/防火墙 | 逐层验证 |
| 拉取失败 | 认证/网络/mirror | 逐项排查 |
9. 最佳实践清单
□ 启动即配 --restart 与 HEALTHCHECK,让"起不来"尽早暴露
□ 应用日志统一写 stdout/stderr(进 docker logs)
□ 排障按 SOP 顺序:状态→日志→inspect→events→stats→exec
□ 准备好调试镜像(netshoot 等),应对容器无工具
□ 明确资源 limits,OOM 有边界可查
□ 构建失败用 --no-cache/--progress=plain 复现
□ 高发问题沉淀为排查手册
□ 别乱删容器,先留证据
一句话原则
排障不是乱试,
而是"退出码给方向、日志给证据、现场给真相"的层层逼近。
小结
Docker 排障与调试,本质是用正确的信息源层层逼近根因:退出码告诉方向(137=OOM、127=命令缺失)、日志提供应用证据、inspect/events还原配置与变迁、exec/调试镜像进入现场取证。落地记住五件事:先看退出码再读日志、进现场用 exec 或 netshoot、OOM 用 OOMKilled + dmesg 定位、构建失败用 –no-cache 复现、沉淀一套排障 SOP。当排障从"靠感觉重试"变成"有路径有工具",Docker 环境里的每一次事故都会更快止血、更准定位、不再反复。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。