背景
服务器上跑着 5 个容器。有天大屏打不开,Nginx 报 502。
第一反应:哪个容器挂了?为什么挂?
docker ps 只能看到"容器活着",看不到"里面发生了什么"。
原因
容器是一层封装。默认只能看到它的"外壳状态"(Up / Exited),要看内部,得用 docker logs、docker exec、docker inspect 这些工具"进到里面看"。
排查顺序应该是:
1. 看容器状态 → docker ps
2. 看容器日志 → docker logs
3. 进容器内部看 → docker exec
4. 看容器配置 → docker inspect
5. 看资源占用 → docker stats
解决
第一步:看容器状态
bash
docker ps -a
关键看两列:
STATUS:是 Up 还是 Exited?有没有 (unhealthy)?
PORTS:端口映射对不对?
bash
docker compose ps
如果容器在反复重启(Restarting),说明启动时就失败了------直接看日志。
第二步:看容器日志(最常用)
bash
# 最后 100 行
docker logs --tail 100 dashboard-dashboard_a-1
# 实时跟踪(类似 tail -f)
docker logs -f dashboard-dashboard_a-1
# 带时间戳
docker logs -t dashboard-dashboard_a-1
# 看最近 10 分钟的
docker logs --since 10m dashboard-dashboard_a-1
日志里重点找:
Error、Exception、Traceback
Connection refused、Access denied
OOMKilled(内存被打爆了)
第三步:进容器内部看
容器能起来但行为不对------进去看:
bash
docker exec -it dashboard-dashboard_a-1 /bin/bash
如果容器很精简(没有 bash):
bash
docker exec -it dashboard-dashboard_a-1 /bin/sh
进去后能做的事:
bash
# 看进程
ps aux
# 看端口
netstat -tlnp
# 或
ss -tlnp
# 看环境变量
env
# 看文件
ls -la /app
# 看网络通不通
curl -v http://db:3306
第四步:看容器配置
想确认环境变量、挂载、健康检查:
bash
# 完整配置
docker inspect dashboard-dashboard_a-1
# 只看环境变量
docker inspect dashboard-dashboard_a-1 --format '{{json .Config.Env}}' | jq
# 只看挂载
docker inspect dashboard-dashboard_a-1 --format '{{json .Mounts}}' | jq
# 只看端口映射
docker inspect dashboard-dashboard_a-1 --format '{{json .NetworkSettings.Ports}}' | jq
# 只看健康检查
docker inspect dashboard-dashboard_a-1 --format '{{json .Config.Healthcheck}}' | jq
第五步:看资源占用
容器"慢"或"卡":
bash
# 实时资源占用
docker stats
# 只跑一次(不持续刷新)
docker stats --no-stream
关键看:
MEM USAGE / LIMIT:内存用了多少,接近上限就是快 OOM 了
CPU %:CPU 占用
NET I/O:网络流量
实战案例
大屏 502 的排查过程:
bash
# 1. 看状态
docker ps -a | grep dashboard
# 输出:dashboard_a Up 2 minutes (unhealthy)
# 2. 看日志
docker logs --tail 50 dashboard-dashboard_a-1
# 输出:Can't connect to MySQL server on 'db'
# 3. 看数据库容器
docker ps | grep mariadb
# 输出:my-mariadb Up 5 seconds (health: starting)
# 4. 看数据库日志
docker logs --tail 30 my-mariadb
# 输出:InnoDB initialization... (还在启动)
# 5. 结论:数据库刚重启,Flask 太快连了
解决方案:给数据库加 healthcheck,让 Flask 等它健康再启动。
三个坑
坑 1:只看 docker ps,不看 -a
docker ps 只显示正在运行的容器。挂掉的容器要 docker ps -a 才看得到。
排查第一步永远是 docker ps -a------先确认容器是死是活。
坑 2:docker logs 默认只显示全部
有的容器日志几万行,docker logs xxx 会刷屏。加 --tail 100 只看最近 100 行。
而且 docker logs 看不到进程内部状态------要看进程,必须 docker exec 进去。
坑 3:docker exec 进不去,报 exec: "bash": not found
精简镜像(Alpine、Distroless)没有 bash。改用 /bin/sh:
bash
docker exec -it my-container /bin/sh
如果连 sh 都没有,用 docker inspect 看配置,或者在 Dockerfile 里加一个调试用的 shell。