切换语言
切换主题

Docker 日志管理实战:从驱动配置到集中收集

凌晨两点,手机震动了一下。生产服务器磁盘告警,阈值 85%。

我翻身打开笔记本,SSH 登上去,心跳有点快。df -h 一看,根分区只剩 12% 的空间。排查了一圈,最后在 /var/lib/docker/containers 里找到了罪魁祸首——一个跑了两周的 Nginx 容器,日志文件已经膨胀到 12GB。

说实话,我当时挺崩溃的。Docker 默认不会限制日志大小,这点很多人不知道。那个容器每天吐几万条访问日志,json-file 驱动老老实实全记下来,两周就把磁盘塞满了。

后来我把那个日志文件删掉,又给所有容器加了轮转配置。这事儿折腾到凌晨四点。

那晚之后,我花了一周时间系统梳理 Docker 日志管理的东西——从日志驱动选择、轮转参数配置,到多容器环境的集中收集方案。这篇文章就是那次踩坑的总结,希望能帮你少走弯路。

一、Docker 日志驱动全景解析

先说个基础概念:Docker 容器的日志不是随便写的,它通过”日志驱动”来决定日志往哪去、怎么存。

Docker 支持多种日志驱动,每种都有适用的场景。你运行一个容器时,Docker 默认用 json-file 驱动——就是把 stdout 和 stderr 的内容,以 JSON 格式写到本地文件里。这个文件存放在 /var/lib/docker/containers/<容器ID>/<容器ID>-json.log

json-file 的好处是简单。不需要额外配置,日志格式统一,Docker 命令(docker logs)能直接读取。但它的坑也很明显:默认无大小限制。容器持续运行,日志就持续累积,直到磁盘撑爆。

下面这张表整理了 6 种常用驱动:

驱动适用场景结构化支持依赖外部服务性能影响
json-file开发调试、单机部署是(自动 JSON)
syslog企业已有 syslog 基础设施否(需解析)是(rsyslog)
journaldsystemd 环境部分
fluentd云原生可观测栈、日志集中收集是(自定义 tag)是(Fluentd 服务)
gelfGraylog 日志平台用户是(Graylog)
none禁用日志、临时容器

json-file 和 syslog 是最常见的两种选择。json-file 用于本地调试和轻量部署,syslog 则适合有现成 syslog 基础设施的企业——日志直接投到 rsyslog 或 syslog-ng,由集中日志系统统一处理。

journald 驱动把日志交给 systemd journal。如果你的服务器用 systemd 管理服务(大多数现代 Linux 发行版都是),journald 是个方便的选择,日志可以用 journalctl 命令查看。

fluentd 和 gelf 是面向集中日志收集的驱动。fluentd 可以把日志投送到 Elasticsearch、Kafka、云存储等多种后端;gelf 则是 Graylog 平台的专用格式。这两种驱动适合多容器集群环境,但需要额外部署日志收集服务。

none 驱动干脆禁用日志。有些临时容器或批处理任务,日志不重要,用 none 可以省点资源。

怎么选?

单机部署、开发调试:json-file 就够了,记得加轮转参数(下一节讲)。企业有 syslog:用 syslog,复用现有基础设施。容器集群、需要集中查看日志:fluentd 或 Loki(后面详细说)。临时容器、日志没用:直接 none。

二、日志轮转配置实战

回到开头那个问题:日志文件膨胀到 12GB。怎么避免?加轮转参数。

json-file 驱动支持三个关键参数:

  • max-size:单个日志文件的最大容量。超过这个值,Docker 会创建新文件,旧文件编号递增。比如 max-size=10m,单文件最大 10MB。
  • max-file:保留的历史文件数量。超过这个数量,最老的文件会被删除。比如 max-file=3,最多保留 3 个历史文件 + 1 个当前文件。
  • compress:是否压缩轮转后的旧文件。默认 false。设为 true 可以节省磁盘空间,但会稍微增加 CPU 开销。

这三个参数的组合,能有效控制日志占用的磁盘空间。比如 max-size=10m, max-file=3,日志最多占用 30MB(加上压缩会更小)。

配置方式:全局 vs 单容器

Docker 日志轮转可以在三个层级配置:

1. 全局配置(daemon.json)

适用于所有容器,一劳永逸。在 /etc/docker/daemon.json 添加:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3",
    "compress": "true"
  }
}

改完重启 Docker daemon:sudo systemctl restart docker。之后所有新容器都会继承这个配置。

注意:全局配置只对新建容器生效。已有的容器需要单独处理,或者删掉重建。

2. 单容器配置(docker run)

适合给某个容器单独定制参数:

docker run -d \
  --name nginx \
  --log-driver json-file \
  --log-opt max-size=50m \
  --log-opt max-file=5 \
  --log-opt compress=true \
  nginx:alpine

高流量应用可以放宽参数,比如 max-size=50m, max-file=10,允许更大的日志空间。

3. Docker Compose 配置

这是最常用的方式,生产部署基本都用 Compose:

version: "3.9"
services:
  webapp:
    image: webapp:latest
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
        compress: "true"

  nginx:
    image: nginx:alpine
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "5"

每个服务可以单独配置,灵活性高。

生产环境推荐值

SigNoz 的 2024 年实践指南给了一些建议:

  • 开发/测试环境max-size=10m, max-file=3,够用就行。
  • 中等流量应用max-size=50m, max-file=5,保留更多历史日志便于排查。
  • 高流量应用max-size=100m, max-file=10,避免日志轮转过快导致历史丢失。

说实话,具体数值要看你的业务场景。关键原则是:根据磁盘容量和日志重要性,找到一个平衡点。磁盘大、日志重要——保留多一点;磁盘紧张、日志不重要——收紧一点。

三、集中式日志收集方案对比

单机环境的日志轮转够用了。但如果你有十几个、几十个容器,日志分散在各个机器上,排查问题就很麻烦——你得登录每台服务器,docker logs 一个个看。

集中式日志收集就是解决这个问题:把所有容器的日志汇总到一个地方,统一存储、统一查询。

目前主流方案有三类:

ELK Stack(Elasticsearch + Logstash + Kibana)

ELK 是经典方案,存在很多年了。Logstash 收集日志,Elasticsearch 存储和索引,Kibana 提供可视化查询界面。

优点是功能强大——全文检索、复杂查询、可视化图表,生态成熟。缺点也明显:资源消耗高。Elasticsearch 本身就是个重量级服务,内存占用经常几个 GB;Logstash 也不轻,配置复杂,学习成本高。

适合大型企业,有专门的运维团队维护,日志量大、需要复杂查询的场景。

EFK(Fluentd 替代 Logstash)

EFK 是 ELK 的变种,用 Fluentd 替换 Logstash。Fluentd 更轻量,内存占用几百 MB,插件生态丰富,支持多种输入输出源。

配置上比 Logstash 洁一些,但 Elasticsearch 的重量没变。整体资源消耗仍然偏高,适合中大型团队。

Loki + Promtail + Grafana

Loki 是 Grafana Labs 推出的日志系统,设计理念很特别:不建全文索引,只索引日志的标签(如容器名、应用名),日志内容存储在压缩文件里。查询时用 grep 方式匹配,性能足够好。

这种设计让 Loki 极轻量——内存占用几百 MB,存储成本比 Elasticsearch 低很多。Promtail 是 Loki 专用采集代理,配置简单;Grafana 做查询界面,和 Loki 无缝集成。

适合云原生环境,尤其是 Kubernetes。小团队、预算有限,Loki 是性价比很高的选择。

方案对比表

方案优点缺点适用规模成本
ELK功能强大、查询灵活、生态成熟资源消耗高、配置复杂、存储成本高大型企业
EFKFluentd 轻量、插件丰富Elasticsearch 仍重、配置仍复杂中大型中高
Loki极轻量、低成本、云原生友好查询功能较弱、不适合全文检索小型/K8s

怎么选型?

我给个简单建议:

  • 小团队(< 10 人),预算有限:Loki。部署简单,资源消耗低,Grafana 界面友好。
  • 中型团队(10-50 人),有一定运维能力:Loki 或 EFK,看日志量。
  • 大型企业,有专业运维团队:ELK。功能全面,生态成熟,值得投入。

如果你已经用 Grafana 做监控,Loki 几乎是天然选择——同一个界面看指标和日志,体验很流畅。

四、生产环境避坑指南

最后一章,聊几个我踩过的坑,给你提个醒。

1. 忘记配置轮转,磁盘爆满

这是最常见的坑。很多人部署容器时压根没想到日志轮转,结果几个月后磁盘告警,排查才发现日志文件几十 GB。

建议:在 Docker daemon.json 里配置全局默认值,新建容器自动继承。别指望记得在每次 docker run 时加参数——人会忘,配置不会。

2. 容器重启,日志丢失

json-file 驱动有个特性:容器删除后,日志文件跟着删除。如果你重启容器时用的是 docker rm + docker run,而不是 docker restart,日志就没了。

这对排查历史问题是个隐患。比如某个容器凌晨崩溃重启,你想看崩溃前的日志,但容器已经被重建,日志已经消失。

建议

  • docker restart 重启容器,而不是删除重建。
  • 关键应用的日志,用 fluentd 或 syslog 驱动投送到外部存储,避免容器删除导致日志丢失。
  • 定期备份重要日志文件,尤其是生产环境。

3. Fluentd 地址配置错误

用 fluentd 驱动时,日志通过 TCP 发送到 Fluentd 服务。如果 Fluentd 地址配置错了,容器启动不会报错,但日志不会被收集——你以为日志在集中存储里,实际丢在传输路上。

配置示例:

docker run -d \
  --log-driver fluentd \
  --log-opt fluentd-address=127.0.0.1:24224 \
  --log-opt tag="docker.&#123;&#123;.Name&#125;&#125;" \
  my-web-app

fluentd-address 必须和 Fluentd 服务实际监听的地址一致。端口默认 24224,TCP 协议。

排查方法

  • 先确认 Fluentd 服务正常运行:curl http://localhost:24224netstat -tlnp | grep 24224
  • docker inspect &lt;容器ID&gt; 查看日志驱动配置是否正确。
  • Fluentd 日志里查看是否收到 Docker 发来的日志流。

4. 监控和告警

日志管理不是配置完就结束了,还需要监控。

两个关键指标

  • 磁盘空间:定期检查 /var/lib/docker/containers 目录大小。设置告警阈值,比如超过 10GB 就通知。
  • 日志延迟:集中收集场景,监控 Fluentd 或 Loki 的写入延迟。延迟过高可能是网络问题或存储瓶颈。

可以用 Prometheus + Grafana 监控,或者更简单——写个脚本定期检查,配合 Cron 执行。

总结

文章讲了 Docker 日志管理的几个关键环节:

  1. 日志驱动选择:json-file 最通用,syslog 适合企业基础设施,fluentd 用于集中收集。
  2. 日志轮转配置max-size + max-file 组合,全局配置省心,单容器配置灵活。
  3. 集中收集方案:小团队用 Loki,大企业用 ELK,看规模和预算。
  4. 避坑指南:全局默认轮转、避免日志丢失、排查 Fluentd 地址、监控磁盘空间。

最后给个快速配置模板:

// /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3",
    "compress": "true"
  }
}

行动建议:如果你还没配置日志轮转,现在就去检查。看看 /var/lib/docker/containers 目录有没有超大日志文件,给 daemon.json 加上轮转参数,重启 Docker daemon。几分钟的事,能省你凌晨两点起床处理磁盘告警的麻烦。

Docker 日志轮转配置

为 Docker 容器配置日志轮转,防止日志文件撑爆磁盘

⏱️ 预计耗时: 10 分钟

  1. 1

    步骤1: 检查当前日志状态

    执行以下命令,查看容器日志占用情况:

    ```bash
    # 查看日志目录总大小
    du -sh /var/lib/docker/containers

    # 查看各容器日志大小
    docker ps -q | xargs -I {} sh -c 'echo -n "{}: "; docker inspect --format="{{.LogPath}}" {} | xargs du -sh 2>/dev/null || echo "N/A"'
    ```

    如果发现某个容器日志超过 1GB,就需要配置轮转了。
  2. 2

    步骤2: 配置全局默认轮转

    编辑 `/etc/docker/daemon.json`,添加日志驱动配置:

    ```json
    {
    "log-driver": "json-file",
    "log-opts": {
    "max-size": "10m",
    "max-file": "3",
    "compress": "true"
    }
    }
    ```

    参数说明:
    - max-size: 单文件最大 10MB
    - max-file: 保留 3 个历史文件
    - compress: 压缩旧文件节省空间
  3. 3

    步骤3: 重启 Docker 生效

    执行重启命令使配置生效:

    ```bash
    sudo systemctl restart docker
    ```

    **注意**:全局配置只对新容器生效,已有容器需要重建或单独配置。
  4. 4

    步骤4: 验证配置

    创建测试容器验证配置是否生效:

    ```bash
    # 创建测试容器
    docker run -d --name test-nginx nginx:alpine

    # 查看日志配置
    docker inspect --format='{{.HostConfig.LogConfig}}' test-nginx
    ```

    输出应显示 `max-size=10m,max-file=3` 参数。
  5. 5

    步骤5: 清理旧容器日志(可选)

    如果已有容器日志过大,可以手动清理:

    ```bash
    # 方法1:清空日志文件(不重启容器)
    sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' 容器名)

    # 方法2:重建容器(推荐)
    docker rm -f 容器名
    docker run ... # 带上日志参数重新创建
    ```

    重建后新容器会继承全局配置。

常见问题

Docker 默认日志驱动是什么?为什么不限制大小?
Docker 默认使用 json-file 驱动,将容器的 stdout 和 stderr 以 JSON 格式写入本地文件。默认不限制大小是为了保证日志完整性,避免丢失排查信息。但这也导致长期运行的容器日志会无限增长,必须手动配置轮转参数。
max-size 和 max-file 参数怎么搭配最合理?
推荐组合:开发环境 `max-size=10m, max-file=3`(总占用 30MB);生产环境 `max-size=50m, max-file=5`(总占用 250MB);高流量应用 `max-size=100m, max-file=10`(总占用 1GB)。关键是根据磁盘容量和排查需求平衡。
容器删除后日志还在吗?如何持久化保存?
json-file 驱动下,容器删除时日志文件会一起删除。持久化方案:1)使用 fluentd/syslog 驱动投送到外部存储;2)定期备份 `/var/lib/docker/containers` 目录;3)使用 `docker restart` 而非删除重建来重启容器。
ELK 和 Loki 怎么选?小团队适合哪个?
小团队(&lt;10人)推荐 Loki:部署简单、内存占用仅几百 MB、存储成本低、与 Grafana 无缝集成。ELK 功能强大但资源消耗高(Elasticsearch 内存经常几个 GB),适合有专业运维团队的大型企业。如果已在用 Grafana 监控,Loki 是天然选择。
Fluentd 地址配置错误会有什么问题?如何排查?
地址配置错误时容器能正常启动,但日志不会被收集,排查时才发现日志丢失。排查步骤:1)确认 Fluentd 服务运行状态 `netstat -tlnp | grep 24224`;2)检查容器日志配置 `docker inspect --format='{{.HostConfig.LogConfig}}' 容器ID`;3)查看 Fluentd 日志是否收到 Docker 发来的数据流。
已有容器怎么应用新的日志轮转配置?
全局配置 `daemon.json` 只对新容器生效。已有容器的处理方式:1)重建容器(推荐):`docker rm -f 容器名` 后用新配置重建;2)单容器配置:`docker update --log-opt max-size=10m 容器名`(部分参数支持热更新);3)手动清空日志:`truncate -s 0 $(docker inspect --format='{{.LogPath}}' 容器名)`。
如何监控 Docker 日志磁盘占用?
监控方案:1)简单脚本 + Cron:定期执行 `du -sh /var/lib/docker/containers`,超过阈值发送告警;2)Prometheus + node_exporter:监控磁盘使用率;3)日志系统自带监控:Loki/Fluentd 提供写入延迟指标。建议设置磁盘告警阈值(如超过 10GB 通知),避免凌晨被叫起来处理。

10 分钟阅读 · 发布于: 2026年4月30日 · 修改于: 2026年5月13日

相关文章

BetterLink

想持续收到这个主题的更新?

你可以直接关注作者更新、订阅 RSS,或者继续沿着系列入口往下读,避免下次又回到搜索结果重新找。

关注公众号

评论

使用 GitHub 账号登录后即可评论