第 12 章 · 日志管理:logging driver 与集中式日志
第 12 章 · 日志管理
12.1 Docker 日志基础
Docker 的日志架构基于日志驱动(Logging Driver),每个容器的 stdout 和 stderr 都会被驱动捕获。
日志流向
容器进程
│
├── stdout ──→ Docker 日志驱动 ──→ 存储后端
│ │
└── stderr ──→ Docker 日志驱动 ──→ ├── 本地文件(默认)
├── syslog
├── journald
├── fluentd
├── json-file(默认)
└── ...
12.2 Compose 中的日志配置
基本配置
services:
web:
image: myapp:latest
logging:
driver: json-file # 默认驱动
options:
max-size: "10m" # 单个日志文件最大 10MB
max-file: "3" # 最多保留 3 个文件
compress: "true" # 压缩轮转日志
常用日志驱动
| 驱动 | 说明 | 适用场景 |
|---|
json-file | 默认,JSON 格式写入本地文件 | 开发、单机生产 |
local | 优化的本地驱动,更高效 | 替代 json-file |
syslog | 发送到 syslog 服务器 | 传统运维环境 |
journald | 发送到 systemd journal | CentOS/RHEL 系统 |
fluentd | 发送到 Fluentd | 集中式日志 |
awslogs | 发送到 AWS CloudWatch | AWS 环境 |
gelf | 发送到 Graylog | Graylog 环境 |
none | 禁用日志 | 不需要日志的服务 |
各驱动配置示例
services:
# json-file(默认)
app:
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
tag: "{{.Name}}/{{.ID}}" # 日志标签格式
# local 驱动(推荐替代 json-file)
app-local:
logging:
driver: local
options:
max-size: "10m"
max-file: "5"
# syslog
app-syslog:
logging:
driver: syslog
options:
syslog-address: "tcp://192.168.1.100:514"
syslog-facility: "daemon"
tag: "myapp"
# fluentd
app-fluentd:
logging:
driver: fluentd
options:
fluentd-address: "localhost:24224"
tag: "myapp.{{.Name}}"
# awslogs
app-aws:
logging:
driver: awslogs
options:
awslogs-group: "/docker/myapp"
awslogs-region: "us-east-1"
awslogs-stream-prefix: "web"
# gelf(Graylog)
app-gelf:
logging:
driver: gelf
options:
gelf-address: "udp://graylog:12201"
tag: "myapp"
12.3 全局日志驱动配置
Docker daemon 级别配置
// /etc/docker/daemon.json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5",
"compress": "true"
}
}
# 重启 Docker 使配置生效
sudo systemctl restart docker
# 查看当前日志驱动
docker info --format '{{.LoggingDriver}}'
💡 最佳实践:在 daemon.json 中设置全局默认日志驱动和轮转策略,防止日志文件占满磁盘。这是生产环境最常见的"磁盘空间不足"根因之一。
12.4 日志查看与管理
Compose 日志命令
# 查看所有服务日志
docker compose logs
# 实时跟踪
docker compose logs -f
# 跟踪指定服务
docker compose logs -f web
# 最后 N 行
docker compose logs --tail 100 web
# 按时间过滤
docker compose logs --since 5m # 最近 5 分钟
docker compose logs --since "2026-05-10T10:00:00"
docker compose logs --until "2026-05-10T12:00:00"
# 显示时间戳
docker compose logs -t web
# 不跟随(一次性输出)
docker compose logs --no-log-prefix web
日志输出格式
# 默认格式
web-1 | 2026-05-10 10:30:00 INFO Starting application...
db-1 | 2026-05-10 10:30:01 LOG: database system is ready
# 带时间戳(-t 参数)
web-1 | 2026-05-10T02:30:00.000000000Z 2026-05-10 10:30:00 INFO Starting...
直接从 Docker 查看
# 查看容器日志(绕过 Compose)
docker logs <container_name>
docker logs -f --tail 50 <container_name>
# 查看日志文件位置
docker inspect --format='{{.LogPath}}' <container_name>
# /var/lib/docker/containers/<id>/<id>-json.log
12.5 集中式日志架构
架构选择
┌─────────────────────────────────────────────────────┐
│ 集中式日志方案对比 │
├──────────────┬──────────────────────────────────────┤
│ EFK Stack │ Elasticsearch + Fluentd + Kibana │
│ │ 功能强大,资源消耗大 │
├──────────────┼──────────────────────────────────────┤
│ ELK Stack │ Elasticsearch + Logstash + Kibana │
│ │ 经典方案,Logstash 较重 │
├──────────────┼──────────────────────────────────────┤
│ Loki Stack │ Loki + Promtail + Grafana │
│ │ 轻量级,与 Prometheus 生态集成 │
├──────────────┼──────────────────────────────────────┤
│ Graylog │ Graylog + MongoDB + Elasticsearch │
│ │ 全功能,社区版免费 │
└──────────────┴──────────────────────────────────────┘
12.6 Loki + Grafana(推荐轻量方案)
完整的 Loki 日志栈
services:
# 应用服务
app:
image: myapp:latest
labels:
logging: "promtail" # 标记需要收集日志
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
tag: "{{.Name}}"
# Promtail — 日志收集器
promtail:
image: grafana/promtail:3.0.0
volumes:
- /var/log:/var/log:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- promtail-config:/etc/promtail
configs:
- source: promtail_config
target: /etc/promtail/config.yml
command: -config.file=/etc/promtail/config.yml
# Loki — 日志存储与查询引擎
loki:
image: grafana/loki:3.0.0
ports:
- "3100:3100"
volumes:
- loki-data:/loki
configs:
- source: loki_config
target: /etc/loki/config.yml
command: -config.file=/etc/loki/config.yml
# Grafana — 可视化
grafana:
image: grafana/grafana:11.0.0
ports:
- "3000:3000"
environment:
GF_SECURITY_ADMIN_PASSWORD: admin
volumes:
- grafana-data:/var/lib/grafana
configs:
promtail_config:
content: |
server:
http_listen_port: 9080
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: docker
docker_sd_configs:
- host: unix:///var/run/docker.sock
refresh_interval: 5s
relabel_configs:
- source_labels: ['__meta_docker_container_name']
regex: '/(.*)'
target_label: 'container'
- source_labels: ['__meta_docker_container_log_stream']
target_label: 'logstream'
loki_config:
content: |
auth_enabled: false
server:
http_listen_port: 3100
common:
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
ring:
kvstore:
store: inmemory
schema_config:
configs:
- from: "2024-01-01"
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
volumes:
loki-data:
grafana-data:
promtail-config:
12.7 Fluentd 集成
services:
app:
image: myapp:latest
logging:
driver: fluentd
options:
fluentd-address: "localhost:24224"
tag: "docker.{{.Name}}"
fluentd:
image: fluent/fluentd:v1.16
ports:
- "24224:24224"
- "24224:24224/udp"
volumes:
- ./fluentd/conf:/fluentd/etc
- fluentd-buffer:/var/fluentd/buffer
<!-- fluentd/conf/fluent.conf -->
<source>
@type forward
port 24224
bind 0.0.0.0
</source>
<match docker.**>
@type file
path /var/fluentd/log/docker
append true
<buffer>
timekey 1h
timekey_use_utc true
flush_mode interval
flush_interval 10s
</buffer>
</match>
12.8 日志格式标准化
结构化日志
services:
app:
image: myapp:latest
environment:
# JSON 格式输出(各语言框架支持)
LOG_FORMAT: json
LOG_LEVEL: info
// 标准 JSON 日志格式
{
"timestamp": "2026-05-10T10:30:00.000Z",
"level": "info",
"message": "Request processed",
"service": "web",
"trace_id": "abc123",
"request": {
"method": "GET",
"path": "/api/users",
"duration_ms": 42
}
}
日志级别管理
| 级别 | 用途 | 生产建议 |
|---|
debug | 详细调试信息 | 关闭 |
info | 一般运行信息 | 开启 |
warn | 警告信息 | 开启 |
error | 错误信息 | 开启 |
fatal | 致命错误 | 开启 |
12.9 日志轮转与清理
防止日志占满磁盘
# 方案一:服务级别配置
services:
app:
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
# 总空间:10MB × 5 = 50MB 每个容器
// 方案二:全局配置(/etc/docker/daemon.json)
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
}
}
手动清理
# 查看 Docker 磁盘使用
docker system df
# 清理所有停止的容器、悬挂镜像、未使用的网络
docker system prune
# 清理所有未使用的卷
docker volume prune
# 核弹选项:清理所有未使用资源(慎用)
docker system prune -a --volumes
12.10 常见日志问题
| 问题 | 原因 | 解决方案 |
|---|
| 磁盘空间不足 | 日志未轮转 | 配置 max-size 和 max-file |
| 日志丢失 | 容器重启 | 使用持久化日志驱动或集中式方案 |
| 日志顺序错乱 | 多实例并发写入 | 使用集中式日志 + 时间戳 |
| 日志量太大 | DEBUG 级别未关闭 | 生产环境设为 info/warn |
| 中文乱码 | 编码问题 | 确保 UTF-8 编码 |
| 日志延迟 | 网络或缓冲 | 调整 flush 间隔 |
12.11 小结
| 概念 | 说明 |
|---|
| 日志驱动 | 控制日志的输出目标,json-file 是默认 |
| 日志轮转 | max-size 和 max-file 防止磁盘占满 |
| local 驱动 | 推荐替代 json-file,性能更好 |
| 集中式日志 | Loki + Grafana 是轻量级首选 |
| 结构化日志 | JSON 格式便于查询和分析 |
| 全局配置 | daemon.json 设置默认日志策略 |
扩展阅读
上一章:第 11 章 · Swarm 部署 ← | 下一章:第 13 章 · 监控 →