讲解

容器日志的模型和虚拟机完全不同:应用应把日志写到标准输出/标准错误(stdout/stderr),Docker 的日志驱动(默认 json-file)把它们落盘,docker logs 统一查看。这带来两条实践铁律:一是容器化应用不要写本地日志文件(容器删了日志没了,盘还会被写爆),二是务必给 json-file 配轮转(daemon.json 里 max-size/max-file,或单容器 --log-opt),否则一个话多的容器能撑爆磁盘。

docker logs 的常用形态:logs 容器名 全量、--tail 100 看末尾、-f 跟踪、--since 10m 看最近十分钟、-t 加时间戳。应用没按 stdout 模型输出时(比如 nginx 默认写文件),官方镜像普遍用软链接把 /var/log/nginx/*.log 指到 /dev/stdout——自建镜像沿用这个套路即可。

排障命令按「由外而内」的顺序用:docker ps -a 看状态与退出码 → docker logs 看应用输出 → docker inspect 看配置全貌(网络、挂载、环境变量,--format 精确取字段)→ docker exec 进容器看现场 → docker stats 看资源占用(CPU/内存/网络 IO,--no-stream 取快照)→ docker events 看守护进程事件流(谁 OOM 了、谁被 kill 了)。这条链覆盖了单机排障九成的场景。

示例

起一个会持续输出日志的容器:

docker run -d --name ohmydocs-verify-noisy alpine:3.21 sh -c 'i=0; while [ $i -lt 5 ]; do echo "心跳 $i"; i=$((i+1)); sleep 1; done; sleep 300'
sleep 3

查看日志(--tail 与 -t 时间戳):

docker logs --tail 3 -t ohmydocs-verify-noisy

inspect 精确取字段——容器的 IP、挂载、重启策略:

docker inspect ohmydocs-verify-noisy --format 'IP={{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}} 重启策略={{.HostConfig.RestartPolicy.Name}}'

stats 快照:当前 CPU 与内存占用(排障「是不是资源不够」的第一步):

docker stats --no-stream --format '{{.Name}}: CPU {{.CPUPerc}} 内存 {{.MemUsage}}' ohmydocs-verify-noisy

清理:

docker rm -f ohmydocs-verify-noisy

常见坑

  • 日志写文件不进 stdout:容器删了日志全丢,且 docker logs 看不到;镜像里把日志路径软链到 /dev/stdout、/dev/stderr。
  • json-file 不轮转:单容器日志几十 GB 把磁盘写满;daemon 或容器级 max-size 必配。
  • 只会 logs 不看 inspect:挂载没挂上、环境变量没传进去、网络进错网段,这些 logs 里都没有——inspect 是另一半真相。
  • events 的窗口错过就没了:events 是实时流不存历史,复盘线上事故要靠日志系统和监控系统,别依赖它。

小结

日志进 stdout、配轮转;排障链 ps → logs → inspect → exec → stats → events。下一章给容器戴上资源紧箍咒。