Skip to content
On this page

Docker 调试与故障排除

调试概述

Docker 调试是识别、分析和解决容器化应用问题的关键技能。有效的调试需要系统性的方法,从容器构建到运行时的各个环节进行排查。

调试工具和命令

1. 基础调试命令

查看容器状态

bash
# 查看所有容器(包括停止的)
docker ps -a

# 实时查看容器资源使用
docker stats

# 查看 Docker 系统信息
docker info

# 查看 Docker 版本
docker version

容器日志分析

bash
# 查看容器日志
docker logs container-name

# 实时查看日志
docker logs -f container-name

# 查看最近的日志
docker logs --tail 50 container-name

# 查看特定时间范围的日志
docker logs --since "2023-01-01T00:00:00" --until "2023-01-02T00:00:00" container-name

# 查看日志的时间戳
docker logs -t container-name

容器详细信息

bash
# 查看容器详细配置
docker inspect container-name

# 查看特定信息(使用格式化输出)
docker inspect --format='{{.State.Running}}' container-name
docker inspect --format='{{.NetworkSettings.IPAddress}}' container-name

2. 进入容器调试

交互式进入容器

bash
# 进入运行中的容器
docker exec -it container-name /bin/sh

# 以 root 用户进入容器
docker exec -u root -it container-name /bin/sh

# 在容器中运行特定命令
docker exec container-name ps aux
docker exec container-name env

调试容器

bash
# 使用调试镜像连接到有问题的容器
docker run -it --rm --volumes-from problematic-container alpine /bin/sh

镜像构建调试

1. Dockerfile 问题调试

检查构建中间层

bash
# 查看镜像层信息
docker history image-name

# 交互式构建(使用特定标签检查中间状态)
docker build --progress=plain -t debug-image .

使用多阶段构建调试

docker
# 调试阶段
FROM node:16-alpine AS debug
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 安装调试工具
RUN apk add --no-cache curl bash vim

# 生产阶段
FROM node:16-alpine AS production
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=debug /app/dist ./dist

2. 构建缓存问题

清理构建缓存

bash
# 清理构建缓存
docker builder prune

# 构建时跳过缓存
docker build --no-cache -t my-app:latest .

# 清理所有构建缓存
docker builder prune -a

运行时调试

1. 容器启动问题

容器立即退出调试

bash
# 检查退出代码
docker inspect --format='{{.State.ExitCode}}' container-name

# 查看完整日志
docker logs --details container-name

# 以交互模式运行
docker run -it --rm my-app:latest /bin/sh

端口访问问题

bash
# 检查端口映射
docker port container-name

# 检查容器网络配置
docker inspect --format='{{.NetworkSettings.Ports}}' container-name

# 测试内部网络
docker exec container-name netstat -tlnp

2. 应用问题调试

检查应用状态

bash
# 查看容器内进程
docker exec container-name ps aux

# 检查监听端口
docker exec container-name netstat -tlnp

# 检查环境变量
docker exec container-name env

# 检查文件权限
docker exec container-name ls -la /app/

网络调试

1. 网络连接问题

检查网络配置

bash
# 查看所有网络
docker network ls

# 检查网络详情
docker network inspect bridge

# 检查容器网络配置
docker inspect --format='{{.NetworkSettings}}' container-name

网络连通性测试

bash
# 从容器内部测试连接
docker exec container-name ping google.com
docker exec container-name curl -I http://other-container:8080

# 使用网络工具容器
docker run --rm -it --network container-network appropriate/curl http://target-service:port

2. DNS 问题调试

bash
# 检查 DNS 配置
docker exec container-name cat /etc/resolv.conf

# 测试 DNS 解析
docker exec container-name nslookup google.com
docker exec container-name dig google.com

存储调试

1. 卷挂载问题

检查卷信息

bash
# 查看所有卷
docker volume ls

# 检查卷详情
docker volume inspect volume-name

# 检查容器挂载信息
docker inspect --format='{{.Mounts}}' container-name

文件权限问题

bash
# 检查文件权限
docker exec container-name ls -la /mounted/path

# 修复文件权限
docker run --rm -v volume-name:/data alpine chown -R 1000:1000 /data

Docker Compose 调试

1. 服务依赖问题

检查服务状态

bash
# 查看所有服务状态
docker-compose ps

# 查看服务日志
docker-compose logs service-name

# 实时查看日志
docker-compose logs -f service-name

# 查看特定服务的配置
docker-compose config --services
docker-compose config --volumes

依赖服务调试

bash
# 检查服务依赖关系
docker-compose config --services | xargs -I {} docker-compose logs {}

# 逐个启动服务进行调试
docker-compose up service1
docker-compose up service2

2. 配置验证

bash
# 验证配置文件语法
docker-compose config

# 查看展开后的配置
docker-compose config --resolve-image-digests

# 测试配置(不启动服务)
docker-compose config --quiet

性能调试

1. 资源使用监控

实时监控

bash
# 实时监控所有容器
docker stats

# 监控特定容器
docker stats container-name

# 以 JSON 格式输出
docker stats --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemPerc}}" container-name

资源限制检查

bash
# 检查容器资源限制
docker inspect --format='{{.HostConfig}}' container-name

# 检查内存使用
docker exec container-name free -h

2. 性能分析工具

使用 cAdvisor

yaml
# docker-compose.yml
version: '3.8'
services:
  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    ports:
      - "8080:8080"
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker:/var/lib/docker:ro

高级调试技术

1. 系统级调试

Docker 守护进程日志

bash
# Linux
sudo journalctl -u docker.service -f

# 或查看日志文件
sudo tail -f /var/log/docker.log

系统资源检查

bash
# 检查系统磁盘使用
docker system df

# 详细查看各部分使用情况
docker system df -v

2. 安全相关调试

检查安全配置

bash
# 检查容器安全选项
docker inspect --format='{{.HostConfig.SecurityOpt}}' container-name

# 检查用户和组
docker exec container-name id

调试最佳实践

1. 系统性调试方法

问题分析流程

  1. 复现问题:确保能稳定复现问题
  2. 收集信息:使用 docker logs, docker inspect 等命令收集信息
  3. 分析原因:根据收集的信息分析可能的原因
  4. 验证假设:通过测试验证假设
  5. 解决问题:实施解决方案
  6. 验证修复:确认问题已解决

2. 日志记录策略

应用日志

docker
FROM node:16-alpine

# 配置日志输出到标准输出
ENV NODE_ENV=production
ENV LOG_LEVEL=info

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .

EXPOSE 3000
CMD ["npm", "start"]

Docker Compose 日志配置

yaml
version: '3.8'
services:
  app:
    image: my-app:latest
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    # 或使用其他日志驱动
    # driver: "fluentd"
    # driver: "syslog"

常见调试场景

1. 应用启动失败

bash
# 步骤1:检查容器是否启动
docker ps -a

# 步骤2:查看日志
docker logs container-name

# 步骤3:进入容器检查
docker exec -it container-name /bin/sh

# 步骤4:检查应用配置
docker exec container-name cat /app/config.json

2. 网络连接问题

bash
# 步骤1:检查网络配置
docker network ls
docker inspect container-name

# 步骤2:测试连接
docker exec container-name ping target-host
docker exec container-name telnet target-host port

# 步骤3:检查防火墙和安全组设置

3. 性能问题

bash
# 步骤1:监控资源使用
docker stats container-name

# 步骤2:检查应用性能
docker exec container-name top
docker exec container-name iostat

# 步骤3:分析瓶颈
docker exec container-name cat /proc/loadavg

调试工具推荐

1. 官方调试工具

  • Docker Bench for Security: 安全配置检查
  • Docker Stats: 资源监控

2. 第三方调试工具

  • Portainer: Docker 管理 UI
  • Dive: 镜像层分析
  • Snyk: 安全漏洞扫描
  • Sysdig: 运行时安全和监控

3. 调试镜像

bash
# 使用调试镜像
docker run -it --rm --privileged --pid=host --network=host appropriate/curl
docker run -it --rm --pid=host nicolaka/netshoot  # 网络调试工具集

预防性调试

1. 健康检查

docker
FROM node:16-alpine

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .

EXPOSE 3000

# 配置健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1

CMD ["npm", "start"]

2. 监控和告警

yaml
version: '3.8'
services:
  app:
    image: my-app:latest
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

小结

Docker 调试是一个系统性的过程,需要掌握各种调试工具和命令。有效的调试不仅需要技术知识,还需要系统性的方法和良好的日志记录策略。通过预防性措施如健康检查和监控,可以减少调试需求并提高系统的可靠性。