Docker 故障排查与调试

Docker 故障排查与调试

掌握Docker问题诊断和调试技巧,快速定位和解决容器化环境中的各种问题。

问题诊断 调试工具 性能优化 错误解决

Docker 故障排查概述

Docker故障排查是一个系统性的过程,需要从多个维度分析和解决问题。有效的故障排查可以:

  • 快速恢复服务可用性
  • 减少系统停机时间
  • 优化资源利用率
  • 提升系统稳定性
  • 预防类似问题再次发生

故障排查应该遵循从简单到复杂、从外部到内部的原则。

为什么故障排查重要?
  • 保障业务连续性
  • 提升运维效率
  • 降低维护成本
  • 增强系统可靠性
  • 提升团队技能
故障排查心态

保持耐心、系统思考、记录过程、验证假设、总结经验。故障是学习的机会,不是失败。

常见问题分类

容器生命周期

容器启动、停止、重启相关的问题。

启动失败 异常退出

网络连接

容器间通信和外部访问问题。

连接超时 DNS解析

存储问题

数据卷、绑定挂载和文件系统问题。

权限错误 磁盘空间

性能问题

CPU、内存、磁盘I/O性能瓶颈。

资源竞争 内存泄漏

安全与权限

访问控制、权限配置和安全策略问题。

权限拒绝 安全策略

系统化故障排查流程

1
问题识别和重现

明确问题现象,尝试重现问题,收集错误信息和时间戳。

2
信息收集

收集日志、指标、配置信息和系统状态。

3
假设和验证

基于收集的信息提出假设,设计实验验证假设。

4
根本原因分析

确定问题的根本原因,而不仅仅是解决表面现象。

5
解决方案实施

实施修复方案,验证解决方案的有效性。

6
预防措施

制定预防措施,避免类似问题再次发生。

基本诊断命令

Docker 基本诊断命令

容器状态检查

# 查看所有容器状态
docker ps -a

# 查看容器详细信息
docker inspect container_name

# 查看容器资源使用
docker stats container_name

# 查看容器日志
docker logs container_name
docker logs -f container_name  # 实时跟踪
docker logs --tail 100 container_name  # 最后100行

# 查看容器内进程
docker top container_name

# 检查容器网络配置
docker exec container_name ip addr
docker exec container_name netstat -tulpn
                        
系统状态检查

# 查看Docker系统信息
docker system info

# 查看磁盘使用情况
docker system df
docker system df -v  # 详细视图

# 查看Docker版本
docker version

# 查看运行中的容器数量
docker ps -q | wc -l

# 检查Docker守护进程状态
sudo systemctl status docker
sudo journalctl -u docker.service  # 查看Docker服务日志
                        

常见问题及解决方案

严重容器无法启动

错误现象
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "app": executable file not found in $PATH: unknown.
诊断步骤

# 1. 检查镜像是否存在
docker images | grep my-app

# 2. 检查Dockerfile中的CMD或ENTRYPOINT
docker history my-app:latest

# 3. 验证可执行文件路径
docker run --rm -it my-app:latest sh
# 在容器内检查:
ls -la /app
which app
                        
解决方案

问题原因: CMD或ENTRYPOINT指定的可执行文件不存在或没有执行权限。

修复方法:


# 在Dockerfile中确保可执行文件存在且有执行权限
FROM alpine:latest
WORKDIR /app
COPY app /app/
RUN chmod +x /app/app
CMD ["/app/app"]
                            

端口已被占用

错误现象
docker: Error response from daemon: driver failed programming external connectivity on endpoint web (hash): Error starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use.
诊断步骤

# 1. 检查端口占用情况
sudo netstat -tulpn | grep :80
# 或者使用 ss 命令
sudo ss -tulpn | grep :80

# 2. 检查是否有其他容器使用相同端口
docker ps --format "table {{.Names}}\t{{.Ports}}"

# 3. 检查Docker服务状态
sudo systemctl status docker
                        
解决方案

问题原因: 宿主机80端口已被其他进程占用。

修复方法:


# 方法1: 停止占用端口的进程
sudo kill -9 $(sudo lsof -t -i:80)

# 方法2: 使用其他端口
docker run -d -p 8080:80 nginx

# 方法3: 停止使用相同端口的容器
docker stop $(docker ps -q --filter "publish=80")
                            

磁盘空间不足

错误现象
Error response from daemon: failed to create shim task: OCI runtime create failed: write /var/lib/docker/overlay2/.../merged/etc/hosts: no space left on device: unknown
诊断步骤

# 1. 检查磁盘使用情况
df -h

# 2. 检查Docker磁盘使用
docker system df
docker system df -v

# 3. 检查大文件和大目录
sudo du -sh /var/lib/docker/* | sort -hr
docker system prune --volumes --all  # 谨慎使用
                        
解决方案

问题原因: Docker存储目录磁盘空间不足。

修复方法:


# 1. 清理未使用的资源
docker system prune
docker volume prune
docker image prune

# 2. 清理所有未使用的资源(包括停止的容器和未使用的镜像)
docker system prune -a --volumes

# 3. 配置日志轮转
# 在 /etc/docker/daemon.json 中添加:
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
                            

网络问题排查

容器网络连接问题

容器间无法通信

# 1. 检查容器网络配置
docker network ls
docker network inspect bridge

# 2. 检查容器IP地址
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name

# 3. 测试容器间连通性
docker exec container1 ping container2_ip
docker exec container1 nslookup container2_name

# 4. 检查防火墙规则
sudo iptables -L
sudo ufw status  # Ubuntu

# 5. 检查Docker网络驱动
docker info | grep -i network
                        
外部无法访问容器服务

# 1. 检查端口映射
docker port container_name

# 2. 测试本地访问
curl http://localhost:port

# 3. 检查容器内服务状态
docker exec container_name ps aux
docker exec container_name netstat -tulpn

# 4. 检查应用日志
docker logs container_name

# 5. 验证防火墙配置
sudo iptables -t nat -L DOCKER
                        
DNS解析问题

# 1. 检查容器DNS配置
docker exec container_name cat /etc/resolv.conf

# 2. 测试DNS解析
docker exec container_name nslookup google.com
docker exec container_name ping google.com

# 3. 检查Docker DNS配置
cat /etc/docker/daemon.json

# 4. 重启Docker服务
sudo systemctl restart docker
                        

性能问题排查

容器性能诊断

CPU性能问题

# 1. 监控CPU使用率
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"

# 2. 查看容器内进程CPU使用
docker exec container_name top

# 3. 检查CPU限制
docker inspect container_name | grep -i cpu

# 4. 分析应用性能
docker exec container_name pidstat 1

# 5. 使用性能分析工具
docker run --rm -it --pid=container:app_container perf record -g -p 1
                        
内存问题诊断

# 1. 监控内存使用
docker stats --format "table {{.Name}}\t{{.MemPerc}}\t{{.MemUsage}}"

# 2. 检查内存限制和实际使用
docker inspect container_name | grep -i memory

# 3. 分析容器内内存使用
docker exec container_name free -h
docker exec container_name cat /proc/meminfo

# 4. 检查内存泄漏
docker exec container_name ps aux --sort=-%mem

# 5. 使用内存分析工具
docker run --rm -it --pid=container:app_container valgrind --tool=memcheck
                        
I/O性能问题

# 1. 监控磁盘I/O
docker stats --format "table {{.Name}}\t{{.BlockIO}}"

# 2. 检查存储驱动
docker info | grep -i storage

# 3. 分析磁盘使用
docker system df -v

# 4. 监控文件系统性能
docker exec container_name iostat -x 1

# 5. 检查数据卷性能
docker volume inspect volume_name
                        

存储问题排查

容器存储问题诊断

数据卷权限问题

# 1. 检查数据卷权限
docker exec container_name ls -la /data

# 2. 检查宿主机文件权限
sudo ls -la /var/lib/docker/volumes/volume_name

# 3. 验证用户ID映射
docker exec container_name id
docker inspect container_name | grep -i user

# 4. 修复权限问题
docker run --rm -v volume_name:/data alpine chown -R 1000:1000 /data
                        
绑定挂载问题

# 1. 检查挂载点
docker inspect container_name | grep -A 10 Mounts

# 2. 验证宿主机目录存在
ls -la /host/path

# 3. 检查SELinux配置(如果启用)
getenforce
sudo setenforce 0  # 临时禁用(测试用)

# 4. 检查AppArmor配置
sudo aa-status
                        
存储驱动问题

# 1. 检查存储驱动
docker info | grep -i storage

# 2. 查看存储驱动状态
docker system df

# 3. 检查存储驱动配置
cat /etc/docker/daemon.json

# 4. 清理存储缓存
docker system prune -a --volumes
                        

高级调试工具

nsenter - 进入容器命名空间

nsenter允许你进入容器的命名空间进行调试,无需在容器内安装调试工具。


# 获取容器PID
PID=$(docker inspect --format '{{.State.Pid}}' container_name)

# 进入容器网络命名空间
sudo nsenter -t $PID -n ip addr

# 进入容器进程命名空间
sudo nsenter -t $PID -p ps aux

# 进入容器挂载命名空间
sudo nsenter -t $PID -m ls -la /app
                        
docker-slim - 容器瘦身和调试

docker-slim可以分析容器内容,帮助识别不必要的文件和依赖。


# 安装docker-slim
curl -L https://downloads.dockerslim.com/releases/1.37.3/dist_linux.tar.gz | tar -xz

# 分析容器
./docker-slim xray --target my-app:latest

# 瘦身容器
./docker-slim build --target my-app:latest
                        
ctop - 容器监控工具

ctop提供类似top的容器监控界面。


# 安装ctop
sudo wget https://github.com/bcicen/ctop/releases/download/v0.7.7/ctop-0.7.7-linux-amd64 -O /usr/local/bin/ctop
sudo chmod +x /usr/local/bin/ctop

# 使用ctop
ctop
                        
dive - 镜像分析工具

dive可以深入分析Docker镜像的每一层,帮助优化镜像大小。


# 安装dive
wget https://github.com/wagoodman/dive/releases/download/v0.10.0/dive_0.10.0_linux_amd64.deb
sudo apt install ./dive_0.10.0_linux_amd64.deb

# 分析镜像
dive my-app:latest
                        

故障排查检查清单

系统化故障排查检查清单

基础检查
  • Docker服务是否运行?
  • 容器是否在运行状态?
  • 是否有足够的磁盘空间?
  • 系统资源(CPU、内存)是否充足?
  • 网络连接是否正常?
容器检查
  • 容器日志是否有错误信息?
  • 容器内应用是否正常启动?
  • 端口映射是否正确配置?
  • 环境变量是否设置正确?
  • 数据卷挂载是否正常?
网络检查
  • 容器间网络是否连通?
  • DNS解析是否正常?
  • 防火墙规则是否阻止连接?
  • 网络驱动配置是否正确?
  • 负载均衡配置是否正确?
存储检查
  • 数据卷权限是否正确?
  • 存储驱动是否正常工作?
  • 绑定挂载路径是否存在?
  • 文件系统类型是否兼容?
  • 存储性能是否满足要求?

问题严重程度评估

严重程度 影响范围 响应时间 解决时间 示例问题
严重 整个系统不可用 立即 4小时内 所有容器无法启动、数据库崩溃
核心功能受影响 2小时内 8小时内 关键服务无法访问、性能严重下降
部分功能受影响 4小时内 24小时内 非核心服务异常、功能受限
轻微影响 1个工作日内 3个工作日内 日志格式问题、监控告警误报

预防措施和最佳实践

完善的监控和告警

建立全面的监控体系,设置合理的告警阈值,确保问题能够被及时发现。

日志标准化和集中管理

使用结构化的日志格式,实施日志集中管理,方便问题追踪和分析。


{
  "timestamp": "2023-01-01T12:00:00Z",
  "level": "ERROR",
  "service": "user-service",
  "request_id": "req-123",
  "message": "Failed to process request",
  "error": "Database connection timeout",
  "user_id": "user-456"
}
                        
健康检查和就绪检查

为容器配置健康检查和就绪检查,确保服务状态可被正确检测。


services:
  web:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    deploy:
      resources:
        limits:
          memory: 512M
        reservations:
          memory: 256M
                        
资源限制和预留

为容器设置合理的资源限制和预留,防止资源竞争和单点故障影响整个系统。

定期演练和知识库建设

定期进行故障演练,建立和维护问题知识库,提升团队故障处理能力。

常见调试误区

误区: 遇到问题就重启容器或服务,而不分析根本原因。

问题: 重启可能暂时解决问题,但根本原因仍然存在,问题会反复出现。

正确做法:

  • 分析日志和监控数据
  • 确定问题发生的根本原因
  • 实施长期的解决方案
  • 建立预防措施

误区: 在没有充分理解问题的情况下,盲目修改各种配置参数。

问题: 可能引入新的问题,使问题更加复杂化。

正确做法:

  • 一次只修改一个配置项
  • 记录每次修改和结果
  • 基于证据进行决策
  • 测试修改的效果

误区: 认为小问题不重要,可以忽略。

问题: 小问题可能是大问题的前兆,忽略它们可能导致更严重的问题。

正确做法:

  • 认真对待每一个异常
  • 建立问题跟踪机制
  • 定期审查和解决积压问题
  • 从每个问题中学习和改进
故障排查与调试掌握!

恭喜!您已经掌握了Docker故障排查与调试的核心知识。现在可以系统化地诊断和解决容器化环境中的各种问题,提升系统稳定性和可靠性。