容器起来了,服务却访问不到。没有报错,没有提示,只有一个沉默的进程悄悄退出。

这种情况是 Docker 使用中最让人抓狂的场景之一——不是挂了,是"失踪"了。而解决这类问题,99% 的突破口都藏在日志里。遗憾的是,很多开发者只会反复 docker ps,却从没认真看过日志。

这篇文章完整梳理 Docker 日志的查看方式、驱动配置、多容器聚合,以及调试容器的实用手段——从"看不到日志"到"定位问题根源",走一遍完整流程。


Docker 日志的工作原理

在具体命令之前,先搞清楚日志是怎么来的。

容器里的进程把内容写到 stdoutstderr,Docker 的日志驱动捕获这两个流,决定把日志存到哪、怎么存。

写入 stdout/stderr

json-file

syslog

journald

fluentd

none

容器内进程

Docker 日志驱动

驱动类型

本地 JSON 文件

系统 syslog

systemd journal

Fluentd 服务

丢弃不保存

这个流程决定了一件事:如果程序把日志写到文件而不是 stdout,docker logs 就看不到任何内容。这是初学者最常踩的坑之一。


基础命令:docker logs

docker logs my-container

这个命令输出容器启动以来的所有日志。容器跑久了日志会很多,通常需要配合参数:

# 只看最后 100 行
docker logs --tail 100 my-container

# 实时跟踪日志输出
docker logs -f my-container

# 显示时间戳
docker logs -t my-container

# 组合使用:带时间戳实时跟踪
docker logs -f -t my-container

# 查看某个时间点之后的日志
docker logs --since 2026-05-10T10:00:00 my-container

# 查看最近 5 分钟的日志
docker logs --since 5m my-container

--since 参数在排查"刚才出了什么问题"时非常有用,比从几千行日志里翻找要快得多。


日志驱动:日志存在哪

Docker 默认使用 json-file 驱动,日志文件存放在:

/var/lib/docker/containers/<container-id>/<container-id>-json.log

查看当前 Docker 默认日志驱动:

docker info | grep "Logging Driver"

查看某个容器使用的日志驱动:

docker inspect my-container | grep -A 5 '"LogConfig"'

各日志驱动的特点如下:

日志驱动对比

json-file

syslog

journald

fluentd

none

默认驱动,本地存储
支持 docker logs 查看
⚠️ 需配置轮转防磁盘爆

发送到 syslog 服务
不支持 docker logs
适合统一日志收集

发送到 systemd journal
支持 journalctl 查看
仅 Linux 可用

发送到 Fluentd
适合生产日志聚合
需要 Fluentd 服务

完全丢弃日志
极少数无状态场景用
生产不建议

配置日志轮转

json-file 驱动默认没有轮转限制,单个日志文件可以无限增长,时间久了会把磁盘撑爆。正确做法是在启动时配置限制:

# 启动时指定日志驱动和选项
docker run \
  --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  my-image

或者在 docker-compose.yml 中统一配置:

services:
  app:
    image: my-image
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

max-size=10m 表示单个日志文件最大 10MB,max-file=3 表示最多保留 3 个轮转文件,超出后自动删除最旧的。

也可以修改 Docker 全局默认配置,对所有容器生效,编辑 /etc/docker/daemon.json

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

修改后重启 Docker:sudo systemctl restart docker


多容器日志聚合查看

实际项目往往由多个容器构成,逐个查看效率很低。

方式一:Docker Compose

# 查看所有服务的日志
docker-compose logs -f

# 只查看某个服务
docker-compose logs -f app

# 只看最后 50 行
docker-compose logs --tail 50

方式二:dozzle(推荐用于本地开发)

dozzle 是一个轻量级的 Web 日志查看工具,一条命令启动:

docker run --name dozzle -d \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -p 8080:8080 \
  amir20/dozzle

浏览器访问 http://localhost:8080,可以看到所有容器的实时日志,支持关键词搜索、颜色高亮、正则过滤,比命令行直观很多。

注意:dozzle 挂载了 Docker socket,具备读取所有容器信息的权限,生产环境使用需评估安全风险,建议只在开发环境部署。


调试容器的实用手段

日志只是起点,很多问题还需要深入容器内部排查。

没有日志

日志不够

有问题

正常

容器出现问题

查看日志
docker logs

日志有报错?

根据报错信息处理

检查程序是否写入 stdout

查看容器配置
docker inspect

环境变量/挂载正确?

进入容器排查
docker exec -it

ps/netstat/curl 手动排查

查看资源占用
docker stats

CPU/内存是否超限?

查看容器详细配置

docker inspect my-container

输出内容包括环境变量、挂载点、网络配置、端口映射、重启策略等完整信息,适合检查"配置有没有传对"。

筛选特定字段:

# 只查看环境变量
docker inspect my-container --format '{{.Config.Env}}'

# 只查看挂载点
docker inspect my-container --format '{{json .Mounts}}' | python3 -m json.tool

# 查看容器 IP
docker inspect my-container --format '{{.NetworkSettings.IPAddress}}'

进入容器排查

# 进入容器(优先用 bash)
docker exec -it my-container /bin/bash

# 没有 bash 时用 sh
docker exec -it my-container /bin/sh

进入后常用的排查命令:

# 查看进程
ps aux

# 查看端口监听
netstat -tlnp
# 或
ss -tlnp

# 测试服务连通性
curl -v http://localhost:8080

# 查看 DNS 解析
cat /etc/resolv.conf
cat /etc/hosts

# 查看磁盘空间
df -h

实时监控资源使用

# 监控所有容器
docker stats

# 只看指定容器
docker stats my-container

输出包括 CPU 使用率、内存占用和限制、网络 IO、磁盘 IO,适合排查"服务变慢"或"内存泄漏"类问题。

查看容器内进程

docker top my-container

显示容器内所有进程的 PID、所属用户和 CPU/内存占用,无需进入容器。


常见问题排查

排查思路

问题类型

容器启动后立即退出

服务访问不到

磁盘报 No space

日志输出有延迟

docker logs 查报错
检查 CMD/ENTRYPOINT
确认有前台进程

docker ps 看端口映射
检查服务监听地址
排查防火墙规则

docker system df 查占用
docker system prune 清理
配置日志轮转

程序关闭 stdout 缓冲
Python 加 -u 参数
Java 配置 log4j 立即刷新

容器启动后立即退出

# 查看退出原因
docker logs my-container

# 查看退出码
docker inspect my-container --format '{{.State.ExitCode}}'

退出码含义:0 正常退出,1 程序错误,137 OOM 或被强杀,143 收到 SIGTERM 信号。

常见原因:Dockerfile CMD 写的是一次性脚本,执行完就退出了,需要改成持续运行的前台进程。

服务启动了但访问不到

按顺序排查:

# 1. 确认端口映射
docker ps --format "table {{.Names}}\t{{.Ports}}"

# 2. 进入容器确认服务在监听
docker exec -it my-container netstat -tlnp

# 3. 确认服务没有只绑定 127.0.0.1
# 如果绑定的是 127.0.0.1:8080,外部是访问不到的,需要改成 0.0.0.0:8080

磁盘报 “No space left on device”

# 查看 Docker 各类资源占用
docker system df

# 清理已停止容器、无用镜像、网络
docker system prune -a

# 只清理悬空镜像
docker image prune

日志输出有延迟

很多编程语言的 stdout 默认有缓冲,写了内容不会立刻输出。常见解决方式:

# Python:禁用缓冲
python -u app.py
# 或设置环境变量
ENV PYTHONUNBUFFERED=1

# Node.js:默认无缓冲,通常不需要处理

日志管理几条原则

  • 生产环境关掉 DEBUG 级别:DEBUG 日志量通常是 INFO 的数倍,既浪费存储又增加查找噪音
  • 敏感信息不入日志:密码、token、手机号做脱敏处理,**** 替换,而不是直接打印
  • 配置日志轮转:不管是 max-size 还是 logrotate,选一种,生产环境必须有
  • 重要系统接外部日志平台:ELK(Elasticsearch + Logstash + Kibana)或 Grafana Loki,方便跨容器检索和告警

小结

Docker 日志排查的核心路径很清晰:

docker logs
查基础日志

docker inspect
查配置信息

docker exec
进容器排查

docker stats
看资源占用

根据证据定位
根因并修复

大多数容器问题,按这条路走下来都能找到答案。与其凭感觉重启容器,不如先把日志看完。

更多推荐