15.11.2 典型故障场景与排查思路
典型故障场景与排查思路需覆盖容器启动失败、服务不可用、性能劣化、网络异常与持久化故障等高频问题。排查总思路遵循“现象—影响面—最近变更—关键指标—最小复现”的链路,优先确认故障范围与业务影响,再回溯镜像版本、配置变更、发布记录与集群事件,最后通过最小化环境复现问题验证修复方案。
常用命令速查(含解释):
# 容器状态与退出码
docker ps -a
# 容器详细配置与挂载
docker inspect <container_name_or_id>
# 查看容器日志(应用层)
docker logs --tail 200 -f <container_name_or_id>
# 容器事件(启动/停止/拉取等)
docker events --since 30m
# 资源消耗(CPU/内存/IO/网络)
docker stats
# 宿主机系统日志与内核事件
journalctl -u docker --since "30 min ago"
dmesg | tail -n 50
# 端口监听与网络状态
ss -lntp
ip a
1. 容器无法启动(ExitCode 非 0)#
典型原因:镜像缺失、入口命令错误、依赖未满足、端口冲突、权限不足。
排查示例:
# 1) 查看容器退出码
docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"
# 2) 拉取镜像失败的确认
docker pull registry.example.com/app:v1.2.3
# 3) 查看日志定位入口错误
docker logs <app_container>
# 4) 检查启动命令与环境变量
docker inspect <app_container> | jq '.[0].Config.Cmd,.[0].Config.Env'
# 5) 进入临时容器验证依赖
docker run --rm -it --entrypoint /bin/sh registry.example.com/app:v1.2.3
# 在容器内执行依赖检查
/opt/app/bin/app --version
最小复现建议:使用相同镜像与最小环境变量启动,逐步加入依赖配置。
2. 服务启动但不可访问#
典型原因:端口映射错误、容器内监听地址不对、宿主机防火墙拦截、网络模式错误。
排查示例:
# 1) 映射端口核对
docker ps --format "table {{.Names}}\t{{.Ports}}"
# 2) 容器内检查监听地址
docker exec -it <app_container> sh -c "ss -lntp"
# 3) 宿主机防火墙检查(Ubuntu/Debian)
ufw status
# 4) 宿主机防火墙检查(CentOS/RHEL)
firewall-cmd --list-all
# 5) 容器内访问自检
docker exec -it <app_container> sh -c "curl -sS http://127.0.0.1:8080/health"
示例修复:应用监听 127.0.0.1 导致外部不可达,需改为 0.0.0.0。
应用配置示例(/opt/app/config.yaml):
server:
host: 0.0.0.0
port: 8080
重启容器生效:
docker restart <app_container>
3. 容器频繁重启#
典型原因:健康检查失败、依赖超时、资源限制过低或进程崩溃。
排查示例:
# 查看重启策略与健康检查
docker inspect <app_container> | jq '.[0].HostConfig.RestartPolicy,.[0].Config.Healthcheck'
# 查看最近的重启事件
docker events --filter container=<app_container> --since 1h
# 查看资源限制与实际消耗
docker inspect <app_container> | jq '.[0].HostConfig.Memory,.[0].HostConfig.NanoCpus'
docker stats <app_container>
修复示例:提升内存限制并延长健康检查间隔:
docker run -d --name app \
--memory=1g --cpus=1.0 \
--health-cmd="curl -f http://127.0.0.1:8080/health || exit 1" \
--health-interval=30s --health-retries=5 \
registry.example.com/app:v1.2.3
4. 性能劣化(CPU/内存/IO/网络)#
排查思路:先定高消耗容器,再定位应用内部问题。
示例流程:
# 1) 定位高消耗容器
docker stats --no-stream
# 2) 宿主机整体负载与IO
top -o %CPU
iostat -x 1 5
vmstat 1 5
# 3) 容器内应用慢查询/GC排查示例(以 Java 为例)
docker exec -it <java_container> sh -c "jstat -gcutil 1 5"
docker exec -it <java_container> sh -c "jstack 1 | head -n 50"
结论示例:IO 等待高 -> 将数据卷迁移至 SSD 或优化写入策略。
5. 镜像相关故障(拉取失败/层损坏)#
排查示例:
# 1) 仓库可达性
curl -I https://registry.example.com/v2/
# 2) 登录凭证
docker login registry.example.com
# 3) 镜像标签检查
docker images | grep app
# 4) 使用镜像校验重拉
docker rmi registry.example.com/app:v1.2.3
docker pull registry.example.com/app:v1.2.3
修复建议:固定基础镜像版本,避免 latest 漂移。
6. 数据持久化异常(挂载失败/权限/数据丢失)#
排查示例:
# 1) 检查挂载路径
docker inspect <app_container> | jq '.[0].Mounts'
# 2) 宿主机目录权限
ls -ld /data/app
id
# 3) SELinux 状态(CentOS/RHEL)
getenforce
修复示例:权限不足导致写入失败:
# 假设容器内以 UID 1001 运行
sudo chown -R 1001:1001 /data/app
数据恢复演练(示例):
# 备份
tar -czf /backup/app_data_$(date +%F).tgz -C /data/app .
# 恢复
tar -xzf /backup/app_data_2024-01-01.tgz -C /data/app
7. 网络异常(DNS/容器间通信/跨主机)#
排查示例:
# 1) DNS 解析
docker exec -it <app_container> sh -c "nslookup redis.service.local"
# 2) 容器间通信
docker exec -it <app_container> sh -c "curl -sS http://redis:6379"
# 3) 检查网络模式与桥接
docker network ls
docker network inspect bridge
常见修复:DNS 失效 -> 指定自定义 DNS 或修复宿主机 resolv.conf。
docker run -d --name app \
--dns 8.8.8.8 --dns 1.1.1.1 \
registry.example.com/app:v1.2.3
练习:构建一条完整排查链路#
- 启动一个错误入口命令的容器,观察退出码与日志。
- 修复启动命令并验证服务可访问。
- 人为限制内存并观察重启与 OOM。
操作示例:
# 1) 错误入口命令
docker run --name badapp -d busybox /not/exist
# 2) 查看退出码与日志
docker ps -a
docker logs badapp
# 3) 正确启动并验证
docker run --name goodapp -d -p 8080:80 nginx:1.25
curl -I http://127.0.0.1:8080
# 4) 限制内存导致 OOM
docker run --name oomapp -d --memory=32m nginx:1.25
docker stats oomapp
故障排查结束后需形成复盘记录:故障触发条件、定位路径、修复动作与预防措施。将常见问题沉淀为标准化手册与告警规则,以缩短 MTTR 并降低重复故障发生率。