Skip to content

Docker 调试技巧:从日志到系统调用的全栈排查指南

在容器化开发中,应用可能因环境差异、配置错误、网络问题或权限限制而异常。掌握高效的调试技巧,能快速定位问题,避免"盲人摸象"。以下是每个开发者都应掌握的 Docker 调试方法,覆盖从基础日志到高级系统调用的全栈排查。

一、docker logs:查看容器输出日志

作用:获取容器的标准输出(stdout)和标准错误(stderr)日志。

基本用法

bash
docker logs <container>

常用选项

  • -f:实时跟踪日志(类似 tail -f
    bash
    docker logs -f my-app
  • --tail 50:仅显示最后 50 行
    bash
    docker logs --tail 50 my-app
  • -t:显示时间戳
    bash
    docker logs -t my-app

适用场景

  • 查看应用启动错误(如端口占用、依赖缺失)
  • 监控运行时异常(如数据库连接失败、JWT 验证错误)
  • 调试 NestJS、Bun 应用的控制台输出

提示:若日志为空,检查应用是否将日志输出到文件而非 stdout/stderr。生产环境应始终将日志重定向到标准输出。

二、docker exec -it <container> sh:进入运行中容器

作用:在已运行的容器中执行命令,常用于交互式调试。

基本语法

bash
docker exec -it <container> <command>

常见用法

1. 进入容器 shell

bash
# Alpine 镜像(无 bash)
docker exec -it my-app sh

# Debian/Ubuntu 镜像
docker exec -it my-app bash

2. 查看文件内容

bash
docker exec my-app cat /app/package.json
docker exec my-app ls -la /app/dist

3. 测试网络连通性

bash
docker exec my-app ping postgres
docker exec my-app curl -v http://api:3000/health

4. 临时运行调试命令

bash
docker exec my-app npm run type-check
docker exec my-app node -e "console.log(process.env)"

注意事项

  • 容器必须处于 running 状态。
  • 若应用以非 root 用户运行,部分系统目录可能无法访问。
  • 生产环境应限制 exec 权限,避免安全风险。

三、docker inspect:查看容器详细配置

作用:获取容器的完整元数据,包括网络、挂载、环境变量、资源限制等。

基本用法

bash
docker inspect <container>

输出结构(JSON 格式)包含:

  • State:运行状态、启动时间、退出码
  • Config:环境变量、工作目录、CMD/ENTRYPOINT
  • NetworkSettings:IP 地址、端口映射
  • Mounts:卷挂载信息(主机路径 → 容器路径)
  • Image:镜像 ID 和配置

实用查询技巧

1. 获取容器 IP

bash
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-app

2. 查看端口映射

bash
docker inspect -f '{{.NetworkSettings.Ports}}' my-app

3. 检查卷挂载

bash
docker inspect -f '{{.Mounts}}' my-app

4. 提取环境变量

bash
docker inspect -f '{{.Config.Env}}' my-app

适用场景

  • 排查端口未正确映射问题
  • 验证 .env 文件或卷是否成功挂载
  • 分析容器为何无法启动(查看 State.Error

四、docker top:查看容器内运行的进程

作用:列出容器内正在运行的进程,类似宿主机的 ps 命令。

基本用法

bash
docker top <container>

输出示例

text
PID                 USER                TIME                COMMAND
12345               node                0:01                node dist/main.js
12367               root                0:00                sh -c npm run dev

适用场景

  • 确认主进程是否正常运行
  • 检测是否有意外进程(如恶意脚本)
  • 排查应用未响应问题(是否卡死或崩溃)

五、高级调试:深入系统层面

当基础命令无法定位问题时,需借助系统级工具进行深入分析。

1. strace:跟踪系统调用

作用:监控进程的系统调用(如文件读写、网络请求、信号处理),用于诊断"卡住"或"无响应"问题。

使用步骤

  1. 进入容器或宿主机
  2. 安装 strace(Alpine: apk add strace;Debian: apt-get install strace
  3. 跟踪目标进程
bash
# 获取容器内 PID
docker top my-app

# 在容器内执行 strace
docker exec -it my-app strace -p <PID>

典型输出

read(3, 0x7fff5fbff5f0, 8192) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=3, events=POLLOUT}], 1, 0) = 1 ([{fd=3, revents=POLLOUT}])

适用场景

  • 应用卡在文件读写
  • 网络请求无响应
  • 权限被拒绝(EPERM

2. tcpdump:抓包分析网络流量

作用:捕获容器的网络数据包,分析网络通信问题。

使用步骤

  1. 在宿主机或容器内安装 tcpdump
  2. 捕获指定接口的流量
bash
# 在宿主机捕获容器流量(需知道容器网络接口)
sudo tcpdump -i docker0 -w capture.pcap host <container-ip>

# 或在容器内抓包(需特权模式)
docker exec -it my-app tcpdump -i any -w /tmp/traffic.pcap

分析工具

  • 使用 Wireshark 打开 .pcap 文件
  • 过滤 HTTP、DNS、TCP 重传等

适用场景

  • 数据库连接超时
  • API 请求未发出或无响应
  • DNS 解析失败

六、调试策略总结

问题类型推荐命令
应用启动失败docker logs, docker inspect
代码未生效docker exec, docker inspect -f '{{.Mounts}}'
端口无法访问docker inspect, docker exec ping/curl
环境变量错误docker inspect -f '{{.Config.Env}}'
容器无响应docker top, strace
网络通信异常tcpdump, curl, ping

七、最佳实践

  1. 日志标准化:确保应用日志输出到 stdout/stderr,便于 docker logs 收集。
  2. 最小化镜像:生产环境使用 distrolessalpine,但调试时可临时使用含调试工具的镜像。
  3. 网络隔离:使用自定义网络(--network)避免 DNS 解析问题。
  4. 权限控制:避免以 root 运行应用,但调试时可临时 docker exec -u root 提权。
  5. 自动化调试:在 CI/CD 中集成日志输出和健康检查,提前发现问题。

结语

Docker 调试不仅是"进容器看日志",更是一套从应用层到系统层的全栈排查能力。掌握 logsexecinspecttop 等基础命令,再结合 stracetcpdump 等高级工具,你就能从容应对容器化环境中的各种"疑难杂症",真正成为 DevOps 时代的高效开发者.