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) 四种日志驱动
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-size 和 max-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 显示为主机总内存。📖 小节
- 四种日志驱动:json-file(默认)、journald、syslog、gelf——生产环境必须配置轮转
docker logs高级过滤:--since/--until时间过滤、--tail行数限制、-f实时追踪docker stats实时监控 CPU/内存/IO,--no-stream一次性快照docker events追踪容器生命周期事件,OOM/die/restart 等关键事件- 日志轮转:
max-size=10m max-file=3防止日志撑满磁盘 - 集中式日志:ELK(企业级)或 Loki+Grafana(轻量/云原生)
📝 作业
- 基础题(难度⭐):启动容器并配置
--log-opt max-size=5m --log-opt max-file=2,用docker logs查看日志并验证轮转生效。 - 进阶题(难度⭐⭐):用
docker stats监控一个压力测试中的容器,记录 CPU 和内存的峰值。 - 挑战题(难度⭐⭐⭐):用
docker events捕获一次容器 OOM 事件,结合docker logs --since定位触发 OOM 的请求或操作。