强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Docker Compose 完全指南 / 第 12 章 · 日志管理:logging driver 与集中式日志

第 12 章 · 日志管理

12.1 Docker 日志基础

Docker 的日志架构基于日志驱动(Logging Driver),每个容器的 stdoutstderr 都会被驱动捕获。

日志流向

容器进程
  │
  ├── 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 journalCentOS/RHEL 系统
fluentd发送到 Fluentd集中式日志
awslogs发送到 AWS CloudWatchAWS 环境
gelf发送到 GraylogGraylog 环境
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-sizemax-file
日志丢失容器重启使用持久化日志驱动或集中式方案
日志顺序错乱多实例并发写入使用集中式日志 + 时间戳
日志量太大DEBUG 级别未关闭生产环境设为 info/warn
中文乱码编码问题确保 UTF-8 编码
日志延迟网络或缓冲调整 flush 间隔

12.11 小结

概念说明
日志驱动控制日志的输出目标,json-file 是默认
日志轮转max-sizemax-file 防止磁盘占满
local 驱动推荐替代 json-file,性能更好
集中式日志Loki + Grafana 是轻量级首选
结构化日志JSON 格式便于查询和分析
全局配置daemon.json 设置默认日志策略

扩展阅读


上一章:第 11 章 · Swarm 部署 ← | 下一章:第 13 章 · 监控 →