Docker: 日志与监控

最后更新:2026-08-26

凌晨 3 点容器崩溃——日志和监控是你快速定位根因的唯一武器。

1. 你将学到


2. 一个运维工程师的真实故事

(1) 痛点:凌晨 3 点 OOM 告警无头绪

生产环境某个容器在凌晨 3 点内存飙升导致 OOM,Charlie 被告警叫醒,但不知道原因——日志文件有 2 GB,docker logs 滚屏太快找不到关键信息,没有历史资源监控数据,只能靠猜。

(2) 日志过滤 + 资源监控的解法

Charlie 用 docker logs --since + grep 组合命令在 30 秒内找到了异常请求。

BASH
# Find OOM-related logs in the last 2 hours
docker logs --since 2h --tail 500 app 2>&1 | grep -i "oom\|memory\|error"

# Check resource usage history
docker stats --no-stream

(3) 收益:30 秒定位根因

从 2 GB 日志中 30 秒定位到 OOM 时间点和异常请求。Charlie 随后配置了日志轮转和 Prometheus 告警,以后凌晨告警会自动带上根因。


3. Docker 日志驱动

(1) 四种日志驱动

100%
graph LR
    CTN["Container<br/>stdout/stderr"] --> DRV["Log Driver"]
    DRV --> JSON["json-file<br/>默认,本地文件"]
    DRV --> JRN["journald<br/>systemd 日志"]
    DRV --> SYS["syslog<br/>远程日志服务器"]
    DRV --> GELF["gelf<br/>ELK/Loki"]
驱动 存储位置 日志轮转 集中式 适用场景
json-file(默认) /var/lib/docker/containers/ 需手动配置 单机开发
journald systemd journal ✅ 自动 systemd 系统
syslog 远程 syslog 服务器 ✅ 服务端 传统日志系统
gelf ELK/Loki ✅ 服务端 集中式日志平台
local 本地文件(优化格式) ✅ 自动 轻量本地日志
none 不记录 - - 高性能/敏感数据

(2) 配置日志驱动

BASH
# Per-container: specify log driver at runtime
docker run -d \
  --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  --name app myapp:1.0
JSON
// Global: /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

4. docker logs 高级用法

▶ 示例:--since 时间过滤(难度⭐⭐)

BASH
# Show logs from the last 2 hours
docker logs --since 2h app

# Show logs from a specific time
docker logs --since "2024-01-15T03:00:00" app

# Show logs between two timestamps
docker logs --since "2024-01-15T03:00:00" --until "2024-01-15T04:00:00" app

▶ 示例:--tail 行数限制(难度⭐)

BASH
# Show last 100 lines
docker logs --tail 100 app

# Follow last 100 lines in real-time
docker logs -f --tail 100 app

▶ 示例:docker stats 实时监控(难度⭐⭐)

BASH
# Real-time resource stats for all containers
docker stats

# One-time snapshot (no streaming)
docker stats --no-stream

# Stats for specific containers
docker stats app db --no-stream

# Custom format
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
💻 输出:

TEXT 📖 仅展示
NAME   CPU %   MEM USAGE / LIMIT
app    2.35%   150MiB / 512MiB
db     0.50%   85MiB / 256MiB

▶ 示例:docker events 事件追踪(难度⭐⭐)

BASH
# Stream Docker daemon events
docker events

# Filter by event type
docker events --filter type=container

# Filter by specific event
docker events --filter event=oom --filter event=die

# Filter by time range
docker events --since "2024-01-15T03:00:00" --until "2024-01-15T04:00:00"
💻 输出:

TEXT 📖 仅展示
2024-01-15T03:24:15Z container oom 67890... (name=app, image=myapp)
2024-01-15T03:24:15Z container die 67890... (exitCode=137, name=app)
2024-01-15T03:24:25Z container start 67890... (name=app, image=myapp)

5. 日志轮转策略

(1) json-file 日志轮转

参数 作用 推荐值
max-size 单个日志文件最大大小 10m
max-file 最多保留几个日志文件 3
labels 日志标签 -
tag 日志标记模板 -

▶ 示例:日志轮转配置(难度⭐⭐)

BASH
# Configure log rotation at container start
docker run -d \
  --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  --name app myapp:1.0
💡 提示: 没有日志轮转的容器是"定时炸弹"——日志文件无限增长最终撑满磁盘。生产环境必须配置 max-sizemax-file,或者使用 local 日志驱动(自带轮转)。

(1) Compose 中的日志配置

YAML
services:
  api:
    image: myapp:1.0
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

6. 集中式日志方案

(1) 三种方案对比

方案 组件 复杂度 适用规模
docker logs 内置 单机/开发
ELK Stack Elasticsearch + Logstash + Kibana ⭐⭐⭐ 企业级
Loki + Grafana Loki + Promtail + Grafana ⭐⭐ 中小型/云原生

7. 完整示例:配置日志轮转与监控

BASH
# ============================================
# Complete walkthrough: Log rotation + monitoring
# Covers: log rotation, stats, events, OOM diagnosis
# ============================================

# 1. Start app with log rotation
docker run -d \
  --name app \
  --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  --memory=256m \
  --restart=on-failure:5 \
  -p 5000:5000 \
  myapp:1.0

# 2. Monitor resource usage
docker stats app --no-stream

# 3. Simulate: trigger OOM by exceeding memory
docker exec app python -c "
import numpy as np
x = np.zeros((50000, 50000))  # Try to allocate ~20GB
"

# 4. Capture the OOM event
docker events --filter event=oom --since 1m

# 5. Find OOM in logs with timestamp
docker logs --since 5m --tail 200 app 2>&1 | grep -i "oom\|memory\|killed"

# 6. Check exit code
docker inspect app --format='ExitCode: {{.State.ExitCode}}, OOMKilled: {{.State.OOMKilled}}'

# 7. Export last 1000 lines for analysis
docker logs --tail 1000 app > app-debug.log 2>&1

# 8. Verify log rotation is working
ls -la /var/lib/docker/containers/$(docker inspect app --format='{{.Id}}')/

❓ 常见问题

Q 日志文件太大会影响磁盘吗?
A 会。默认 json-file 驱动不做日志轮转,日志无限增长。见过生产环境单个容器日志 50 GB 的案例。必须在启动时配置 --log-opt max-size=10m --log-opt max-file=3,或全局在 daemon.json 中设置默认轮转。
Q 如何配置日志轮转?
A 两种方式:① 启动容器时 --log-opt max-size=10m --log-opt max-file=3;② 全局配置 /etc/docker/daemon.json"log-opts": {"max-size": "10m", "max-file": "3"}。生产环境推荐全局配置,避免遗漏。
Q 多个容器日志怎么统一收集?
A 用 gelf 或 syslog 日志驱动,将所有容器日志发送到 ELK/Loki 集中式平台。更推荐的方式:保持 json-file 驱动 + 用 Filebeat/Promtail 采集日志文件,这样 docker logs 仍然可用。
Q 容器重启后日志还在吗?
A 在。容器 restart 不删除日志文件。但 docker rm 删除容器后日志也随之删除。需要持久化日志:① 写入应用文件 + Volume 挂载;② 集中式日志平台实时采集。
Q docker stats 显示的内存是容器还是进程的?
A 容器的。docker stats 显示的是容器 cgroup 中所有进程的总内存使用。LIMIT 是 --memory 设置的上限。如果没设置 --memory,LIMIT 显示为主机总内存。

📖 小节


📝 作业

  1. 基础题(难度⭐):启动容器并配置 --log-opt max-size=5m --log-opt max-file=2,用 docker logs 查看日志并验证轮转生效。
  2. 进阶题(难度⭐⭐):用 docker stats 监控一个压力测试中的容器,记录 CPU 和内存的峰值。
  3. 挑战题(难度⭐⭐⭐):用 docker events 捕获一次容器 OOM 事件,结合 docker logs --since 定位触发 OOM 的请求或操作。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏