容器默认会将 stdout/stderr 输出保存到宿主机的 JSON 文件中,随着容器运行时间增长,日志文件可能占满磁盘,导致服务不可用。同时,分布式环境下查看分散在各主机上的日志极其低效。本文深入讲解 Docker 的日志驱动机制,如何限制日志大小、配置不同的日志驱动(json-file、syslog、fluentd),并搭建 ELK 或 Loki 实现集中日志管理。

一、Docker 日志基础
容器中的应用程序如果输出日志到标准输出(stdout)和标准错误(stderr),Docker 会捕获这些输出并通过日志驱动(logging driver)进行处理。默认驱动是 json-file,将日志写入宿主机的 /var/lib/docker/containers//-json.log 文件。

问题:

容器不限制日志文件大小,可能导致磁盘被写满。

默认驱动不支持日志轮转和压缩。

多主机环境下日志分散,难以统一查看。

二、配置日志驱动
2.1 查看当前日志驱动

docker info | grep "Logging Driver"

2.2 运行时指定日志驱动

# 使用 syslog 驱动
docker run --log-driver syslog --log-opt syslog-address=tcp://192.168.1.10:514 alpine echo "test"

# 使用 fluentd 驱动
docker run --log-driver fluentd --log-opt fluentd-address=192.168.1.10:24224 ...

2.3 全局默认驱动配置(daemon.json)
编辑 /etc/docker/daemon.json:

json
{
“log-driver”: “json-file”,
“log-opts”: {
“max-size”: “10m”,
“max-file”: “3”,
“compress”: “true”
}
}
重启 Docker:systemctl restart docker。

三、常用日志驱动详解
在这里插入图片描述

四、json-file 驱动配置(本地轮转)

# 运行容器时指定
docker run -d --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  --log-opt compress=true \
  nginx

max-size:单个日志文件最大大小(如 10m、1g)。

max-file:最多保留的文件数(轮转后保留旧文件数量)。

compress:是否压缩旧日志。

查看日志文件:

ls /var/lib/docker/containers/<container-id>/
# 会出现:<id>-json.log, <id>-json.log.1.gz 等

五、集中日志收集方案
5.1 使用 ELK(Elasticsearch + Logstash + Kibana)
架构:容器 → 日志驱动 → Logstash → Elasticsearch → Kibana

步骤:

配置 daemon.json 使用 gelf 驱动发送到 Logstash:

json
{
“log-driver”: “gelf”,
“log-opts”: {
“gelf-address”: “udp://localhost:12201”
}
}
启动 Logstash 配置 gelf input:

ruby
input {
gelf {
port => 12201
}
}
output {
elasticsearch {
hosts => [“http://elasticsearch:9200”]
}
}
启动 Elasticsearch 和 Kibana(可通过 Docker Compose)。

5.2 轻量级方案:Loki + Promtail(Grafana 栈)
Loki 是受 Prometheus 启发的日志聚合系统,不索引全文,只索引标签,成本低。

docker-compose 示例:

version: '3'
services:
  loki:
    image: grafana/loki:latest
    ports:
      - "3100:3100"
  promtail:
    image: grafana/promtail:latest
    volumes:
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
      - /var/run/docker.sock:/var/run/docker.sock
    command: -config.file=/etc/promtail/promtail-docker-config.yaml
  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"

在 Grafana 中添加 Loki 数据源,即可通过 LogQL 查询日志。

5.3 使用 Fluentd(最通用)

# 启动 Fluentd 容器
docker run -d --name fluentd \
  -p 24224:24224 \
  -v /var/log/fluentd:/fluentd/log \
  fluent/fluentd:latest

# 运行容器时指定日志驱动
docker run --log-driver fluentd --log-opt fluentd-address=localhost:24224 ...

Fluentd 可将日志转发到 Elasticsearch、S3、Kafka 等。

六、日志驱动常见问题
在这里插入图片描述

七、清理日志命令

# 清理所有容器的日志文件(保留最近 3 天?)
docker container prune --filter "until=72h"

# 手动清理单容器日志文件
truncate -s 0 /var/lib/docker/containers/*/*-json.log

# 使用 logrotate 工具(推荐)
cat /etc/logrotate.d/docker
/var/lib/docker/containers/*/*-json.log {
    daily
    rotate 7
    compress
    missingok
    delaycompress
    copytruncate
}

八、最佳实践
生产环境必须配置日志轮转(max-size / max-file)。

集中日志收集:选择 ELK / Loki / Splunk,避免登录各主机查看。

避免在容器内写日志文件:应输出到 stdout/stderr,由 Docker 驱动统一处理。

使用标签丰富日志:如 --log-opt tag=“{{.ImageName}}|{{.Name}}”(对于 json-file 驱动有效)。

安全考虑:日志中避免输出密码、token 等敏感信息。

监控磁盘使用率:设置告警,避免日志占满导致容器崩溃。

九、小结
Docker 日志管理不仅仅是防止磁盘爆满,更是可观测性的基石。通过选择合适的日志驱动和集中收集工具,你可以轻松查看、搜索和告警,显著提升故障排查效率。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐