在运维工作中,如果运行的一个容器突然挂了,如何排查?
容器突然挂掉是运维中的常见问题,以下是系统化的排查步骤和解决方案,结合关键命令和深度分析:
1. 确认容器状态与退出码
# 查看已停止的容器(重点观察退出码 Exit Code)
docker ps -a | grep -v "Up"
# 检查容器详细状态(包括退出码、时间点)
docker inspect <容器ID> --format='{{.State}}'
- 关键退出码解析:
退出码 含义 常见原因 0
正常退出 任务完成或主动退出 1
应用错误 代码异常/配置错误 137
SIGKILL (强制终止) OOM被杀/ kill -9
139
段错误 (Segfault) 内存越界/空指针 143
SIGTERM (优雅终止) docker stop
触发
2. 查看容器日志
# 获取全部日志(重点检查末尾)
docker logs --tail 100 <容器ID>
# 持续监控日志(复现问题)
docker logs -f <容器ID> 2>&1 | grep -i -E "error|exception|fatal"
- 日志分析要点:
- 应用崩溃栈轨迹(Java/Python 异常栈)
- 数据库连接失败、证书过期等配置错误
- 健康检查连续失败记录
3. 检查资源限制与 OOM
# 确认是否因OOM被杀
dmesg -T | grep -i "killed process"
# 输出示例:Jul 23 10:05:01 host kernel: Out of memory: Killed process 12345 (java)
# 检查容器资源限制
docker inspect <容器ID> --format='{{.HostConfig.Memory}} {{.HostConfig.MemorySwap}}'
- 解决方案:
# 临时增加内存限制(测试用) docker run -d --memory=2g --memory-swap=3g your_image # 永久调整:在docker-compose中配置 services: app: mem_limit: 1.5g memswap_limit: 2g
4. 分析进程崩溃原因
🔍 核心转储分析 (Core Dump)
# 启用核心转储
docker run --ulimit core=-1 -d your_image # 允许生成core文件
# 进入容器查找core文件
docker exec -it <容器ID> find / -name core.*
- 分析工具:
# 使用gdb分析core文件 gdb /path/to/app /path/to/core -ex "bt full" -ex quit
🐞 调试运行
# 以调试模式启动容器
docker run -it --rm --cap-add=SYS_PTRACE your_image sh
# 容器内安装调试工具
apk add gdb lldb # Alpine
apt-get install gdb lldb # Ubuntu
# 附加到进程
gdb -p <PID>
5. 检查健康检查失败
# 示例:Dockerfile中的健康检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8080/health || exit 1
- 查看健康状态:
docker inspect --format='{{json .State.Health}}' <容器ID>
6. 文件系统与权限问题
# 检查容器文件系统变化
docker diff <容器ID> # 查看修改的文件(A-Add, D-Delete, C-Change)
# 以root身份进入停止的容器
docker run -it --rm --entrypoint sh --user root <镜像ID>
- 常见故障:
- 日志文件占满磁盘:
df -h
检查宿主机磁盘 - 权限拒绝:
chown/chmod
修复
- 日志文件占满磁盘:
7. 网络与服务依赖
# 模拟容器网络访问
docker run --rm --network container:<故障容器ID> curlimages/curl http://db:3306
# 检查DNS解析
docker run --rm busybox nslookup redis
- 依赖问题:
- 数据库连接超时
- 服务发现失效(Consul/Etcd)
- 防火墙规则变更
8. 宿主机问题排查
# 检查内核日志
journalctl -k | grep -i docker
# 查看cgroup事件
sudo cat /sys/fs/cgroup/memory/docker/<容器ID>/memory.oom_control
排查流程图
graph TD
A[容器退出] --> B{检查退出码}
B -->|0| C[正常退出]
B -->|137| D[OOM被杀]
B -->|139| E[应用崩溃]
B -->|其他| F[查看日志]
D --> G[调整内存限制]
E --> H[分析Core Dump]
F --> I[检查错误日志]
I --> J[配置错误] --> K[修正配置]
I --> L[依赖服务故障] --> M[检查网络]
自动化运维技巧
-
崩溃自动重启策略:
docker run --restart=on-failure:5 --restart-window=10m your_image
-
监控告警集成:
- Prometheus + Alertmanager 监控容器状态
- 配置规则:容器重启次数 > 3次/5分钟 触发告警
-
故障自愈脚本:
#!/bin/bash CONTAINER="your_app" if [ $(docker inspect -f '{{.State.Status}}' $CONTAINER) == "exited" ]; then docker logs $CONTAINER | mail -s "容器 $CONTAINER 崩溃" admin@example.com docker restart $CONTAINER fi
总结:关键命令速查表
场景 | 命令 |
---|---|
查看退出原因 | docker inspect -f '{{.State.Error}}' <容器ID> |
实时日志 | docker logs -f --tail 50 -t <容器ID> |
检查OOM | dmesg -T | grep -i "killed process" |
分析文件变化 | docker diff <容器ID> |
调试启动 | docker run -it --rm --entrypoint=/bin/sh <镜像> |
资源使用历史 | docker stats --no-stream <容器ID> |
通过以上步骤,90%的容器崩溃问题可快速定位。对于复杂问题,结合 APM工具(如Datadog) 和 分布式追踪(Jaeger) 进行深度诊断。