5.1 调试工具与技巧


5.1 调试工具与技巧

本节摘要:调试工具是故障排查的第一层武器。本节把命令分成三组:compose 内置的 config、ps、top、exec、run 负责项目层面的状态与校验;docker 底层的 inspect、logs、stats、events 负责容器细节;网络层面的 ping、DNS 查询、netstat、tcpdump 负责连通性判断。掌握"什么症状用什么命令"的对应关系,再走一遍 web 连不上数据库的完整案例,你就能把抽象报错翻译成具体动作。

上手前先明确

  1. 能说出三层调试命令的分工,并为指定故障场景选出正确命令
  2. 能用 docker compose config 校验配置,用 ps、top 判断项目运行状态
  3. 能用 docker compose exec 进入容器查看文件、环境变量和进程
  4. 能用 ping、DNS 查询、tcpdump 定位容器间网络问题
  5. 能独立完成一个端到端网络故障的排查流程

一、先分类再动手:三层命令的分工

凌晨两点收到"web 挂了"的消息,你的第一反应是什么?如果答案是 docker compose restart,那这一节就是为你准备的。restart 只能解决进程崩溃,解决不了配置错误、依赖没就绪、网络不通这类真正的问题。正确做法是把手里的命令按三层组织好,像工具箱一样分类摆放:

第一层,compose 内置命令,回答"项目整体怎么样"。config 校验语法,ps 看状态,top 看进程,exec 进容器,run 跑一次性任务,events 看生命周期事件。

第二层,docker 底层命令,回答"单个容器细节怎么样"。inspect 看 JSON 级配置,logs 看输出,stats 看资源,events 看事件流。

第三层,网络命令,回答"容器之间通不通"。ping 服务名测连通,getent 测 DNS 解析,netstat 看监听端口,tcpdump 抓包。

命令 回答的问题 典型场景
compose 内置 docker compose config 语法和合并结果是否正确 修改文件后第一步
compose 内置 docker compose ps / top 哪些容器在跑、进程如何 判断整体状态
compose 内置 docker compose exec / run 容器内部实际状态 进容器查证
docker 底层 docker inspect 挂载、网络、环境变量的真实值 配置与预期不符
docker 底层 docker logs / stats 输出内容与资源占用 找报错、看瓶颈
docker 底层 docker events 容器从创建到删除发生了什么 容器莫名消失
网络 ping / tcpdump 连通性与数据包路径 容器间不通

一个细节先说明:老版本命令写作 docker-compose,新版 Docker 写作 docker compose,两者参数完全一致,只是连字符变成了空格。本书示例沿用 docker-compose 写法,你按自己环境里的版本选择即可。

二、compose 内置命令:从校验到执行

先给一份可以跟着实验的 compose 文件,后面所有命令都围绕它展开:

services: web: image: nginx:1.27-alpine ports: - "8080:80" depends_on: db: condition: service_started networks: - appnet db: image: mysql:8.4 environment: MYSQL_ROOT_PASSWORD: example volumes: - dbdata:/var/lib/mysql networks: - appnet volumes: dbdata: networks: appnet:

关键行解读:depends_on 配了 condition: service_started,只保证 db 容器被创建并启动,不保证 MySQL 已经就绪,后者要靠健康检查,这是第 5.2 节的重点;networks 把两个服务放进同一个自定义网络 appnet,容器间用服务名互访的前提就是这个;具名卷 dbdata 把数据库文件挂出容器,容器重建后数据还在。

六个内置命令逐个说:

  • docker-compose config:校验语法并打印合并后的完整配置。环境变量插值、继承合并之后的最终值都在输出里,一眼能看出"我以为的配置"和"实际生效的配置"差在哪。这是修改文件后的第一动作,比直接 up 省时间。
  • docker-compose ps:列出项目内所有容器的名称、命令、状态、端口映射。Up 只代表进程活着,不代表服务健康;Exited 后面跟着的退出码才是明确线索。
  • docker-compose top:显示项目内各容器里的进程列表,格式类似宿主机的 top。怀疑容器里进程异常、僵尸进程堆积时用它,比挨个进容器快。
  • docker-compose exec:在运行中的容器里执行命令,exec 服务名 bash 直接进入 shell。它不新建容器,操作的是现有容器,适合现场查证。
  • docker-compose run:启动一个一次性容器执行命令,跑完即弃,适合执行数据库迁移、初始化脚本。注意 run 会临时创建新容器,别把临时状态误当成生产环境。
  • docker-compose events:流式输出项目里的事件,容器的创建、启动、停止、删除都会实时打出来。调试"容器为什么被干掉"时,这个命令比猜快得多。

run 和 exec 的选择有一条经验:要改现有容器的现场,用 exec;要在一个干净环境里重放某个命令,用 run。比如验证数据库迁移脚本,run 一个临时容器执行迁移命令,末尾加 --rm 参数让容器退出后自动清理,不留下任何痕迹。

三、docker 底层命令:看细节

compose 命令管项目,docker 命令管单个容器。两者配合使用:

  • docker ps -a:默认只显示运行中的容器,加 -a 把已退出的也列出来。Exited 状态加退出码,是排查的第一条线索。
  • docker inspect:以 JSON 格式输出容器的全部配置。排查卷挂载看 Mounts 段,排查网络看 NetworkSettings 段的 Networks 子段,排查环境变量看 Config.Env。输出很长,建议过滤着看:docker inspect 容器名 | grep -A 5 Mounts,直接跳到关键段落。
  • docker logs:与 compose logs 作用相同,但按容器 ID 或容器名定位,不按服务名。compose 的 logs 本质是对多个容器调用 docker logs 再合并输出。
  • docker stats:实时刷新 CPU 使用率、内存用量、网络 I/O、磁盘 I/O。排查资源瓶颈时开一个终端挂着观察,加 --no-stream 参数可以只输出一次快照。
  • docker events:全 Docker 范围的事件流,compose events 只是按项目过滤后的子集。容器因内存超限被杀死时,这里会出现 oom 事件,比翻日志更快定位。

四、网络调试:从 ping 到抓包

容器间通信有两个默认前提:在同一个网络里、用服务名当主机名。网络排查按从粗到细的顺序来:

  • ping 服务名:docker-compose exec web ping db。通了,说明网络层没问题;不通,先查两个服务的 networks 段是否都写了同一个网络。
  • DNS 解析:ping 通不代表业务通,区分"解析失败"和"连接失败"用 getent hosts db。解析失败查网络配置,连接失败查端口和服务状态。
  • netstat -an:在容器里查看监听端口,确认应用真的在听,而不是配置里写了端口但进程没起来。
  • traceroute:追踪数据包经过的路由路径。容器间在同一个自定义网络里通常一跳直达,出现多跳或超时说明走了意外路径,多半是网络配置串了。
  • tcpdump 抓包:前几步都正常仍不通时,抓包看数据包是否真的到达:docker-compose exec web tcpdump -i eth0 -n -s 0 port 3306。参数含义:-i eth0 指定网卡,-n 不做 DNS 解析避免干扰,-s 0 抓取完整数据包,port 3306 只抓数据库端口。注意 alpine 镜像默认没有 tcpdump,要先 apk add tcpdump,且需要有 root 权限。

⚠️ 两个网络坑提醒:其一,ping 通不等于业务通——ICMP 走的是网络层,业务走的是 TCP 端口,端口没监听照样报连接被拒;其二,部分精简镜像根本没装 ping,ping 不通先确认镜像里有没有这个命令,别急着下结论。

五、进入容器排查的 exec 技巧

docker-compose exec web bash 进入容器后,按固定顺序检查五件事,避免瞎转:

  1. 看进程:ps aux,确认主进程还活着,进程数是否符合预期。
  2. 看监听:netstat -an | grep 80,确认应用端口在监听。
  3. 看环境变量:env | grep 数据库名,确认连接串、密钥是否注入成功。
  4. 看文件:ls 配置目录、cat 配置文件,确认挂载的文件真的出现在容器里、内容是否最新。
  5. 测依赖:curl 或 wget 请求依赖服务的地址,直接验证端到端。

两个 exec 的细节值得记住。第一,exec 只对运行中的容器有效,容器已经退出时命令会报错,这时应该看 docker logs 找退出原因,而不是硬 exec。第二,exec 启动的进程不经过镜像的 entrypoint,entrypoint 里临时导出的环境变量在 exec 的 shell 里看不到,别据此误判变量没配置。

镜像选型上,busybox 体积不到 2MB 却自带 ping、wget、netstat,是理想的临时调试镜像;alpine/git 则适合需要 git 命令的场景。可以临时把调试镜像拉进项目网络做连通测试,测完就删,不污染生产容器。

💡 代码级调试同样可行:容器里可以装 gdb 调试 C 和 C++ 程序,用 pdb 调试 Python 程序。不过容器里装调试器又重又麻烦,我更倾向先加日志缩小范围,日志定位不了的疑难杂症再上调试器。

六、端到端示例:web 连不上数据库

把前面所有工具串起来走一遍。场景:项目启动后 web 报数据库连接失败,报错是 Connection refused。

  1. docker-compose ps 确认 web 和 db 两个容器都在 Up 状态,排除容器没起来的情况。
  2. docker-compose logs web 看完整报错,确认是连接被拒而不是认证失败——两个问题的排查方向完全不同。
  3. docker-compose exec web bash 进入 web 容器。
  4. ping db 测网络层。不通:查两个服务的 networks 段,确认都在 appnet 里;通了,继续下一步。
  5. getent hosts db 确认服务名能解析出 IP;netstat -an 确认 db 容器里的 3306 端口确实在监听。
  6. 网络层全通还失败:检查应用连接串里的主机名是不是 db、端口是不是 3306,这是最常见的低级错误。
  7. 修复后 docker-compose restart web,复测请求恢复。

这个案例的要点不是命令本身,而是顺序:先确认状态,再进容器,先测网络层,再查应用层。每一步都把嫌疑范围缩小一半,七步之内必然收口。补充一个实战细节:web 容器里如果装了 curl,最后一步可以直接 curl 「相关地址请参见官方文档」 验证端口通不通,比 ping 更贴近业务的真实路径。

七、高频问题速查

把前面所有工具对应到四类最常见的故障现象,形成一张速查表,遇到问题直接查:

现象 优先检查 对应工具
容器无法启动 compose 配置、镜像名、宿主机资源、Docker 守护进程 config、ps、logs
容器之间无法通信 是否同网络、防火墙、连通性 exec 加 ping、traceroute
应用访问失败 端口映射、应用监听端口、防火墙 ps、exec 加 netstat
数据卷挂载失败 卷配置、宿主机目录、容器内挂载点 inspect 的 Mounts 段

容器无法启动时,四个方向按成本从低到高查:先 docker-compose config 确认配置能解析,再 docker-compose logs 看启动输出里的报错,然后确认宿主机 CPU、内存、磁盘余量够不够,最后确认 Docker 守护进程本身在运行——Linux 上用 systemctl status docker,Windows 上检查 Docker Desktop 的状态。容器之间无法通信,先确认两个服务都在同一个 networks 段里,再进容器用 ping 和 traceroute 逐跳定位断点。应用访问失败,先确认端口映射正确,再进容器确认应用监听的就是映射的那个端口,最后查宿主机防火墙。数据卷挂载失败,docker inspect 看 Mounts 段的源路径、目标路径和读写标志,比对 compose 里的声明就能发现问题。

本章回顾

  • 先分类再动手:命令分三层,compose 管项目、docker 管容器、网络命令管连通,别拿一个命令硬套所有症状。
  • config 是第一步:改完文件先 docker-compose config 校验,解析错误在 up 之前就暴露。
  • exec 只对运行中容器有效:容器退出了就看日志找原因,不要硬 exec。
  • ping 通不等于业务通:网络层通只能排除一半问题,端口监听和应用逻辑还要单独验证。
  • tcpdump 是最后手段:抓包前先确认镜像里有这个命令且有 root 权限。
  • run 跑一次性任务:迁移、初始化脚本用 docker-compose run,跑完即弃不污染环境。
  • 检查顺序固定:状态、日志、网络层、应用层,每步缩小一半嫌疑范围。

工具认全了,接下来就要面对报错本身。5.2 节我们把最常见的九类错误逐一拆开,每类都给真实报错和修复步骤。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U