Appearance
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. 系统性调试方法
问题分析流程
- 复现问题:确保能稳定复现问题
- 收集信息:使用
docker logs,docker inspect等命令收集信息 - 分析原因:根据收集的信息分析可能的原因
- 验证假设:通过测试验证假设
- 解决问题:实施解决方案
- 验证修复:确认问题已解决
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 调试是一个系统性的过程,需要掌握各种调试工具和命令。有效的调试不仅需要技术知识,还需要系统性的方法和良好的日志记录策略。通过预防性措施如健康检查和监控,可以减少调试需求并提高系统的可靠性。