Docker 日志轮转:容器日志膨胀治理与 logrotate 联动

容器日志轮转封面示意图

本文教你如何解决 Docker 容器日志膨胀问题。一台连续运行半年的宿主机,磁盘使用率在业务没有增长的情况下悄悄爬到 90% 以上,排查后往往落在 /var/lib/docker/containers/ 下几个几百 MB 的 *-json.log 文件上——容器进程持续打印标准输出,默认日志驱动不加轮转,文件只会越大,直到写满磁盘、拖垮同机所有服务。下文先讲如何定位膨胀源,再给出日志驱动内置轮转和 logrotate(Linux 通用日志轮转工具)联动两种方案,附验证方法与踩坑清单,照做即可把日志磁盘占用控制住。

容器日志为什么会无限膨胀

Docker 默认使用 json-file(一种把容器标准输出按行存成 JSON 的日志驱动)记录容器日志。每个容器的日志对应一个固定路径的文件,格式是 /var/lib/docker/containers/<容器ID>/<容器ID>-json.log。这个驱动的问题在于:默认配置下没有任何大小上限,也没有轮转周期,只要容器进程持续输出,文件就会持续增长。

定位膨胀源只需要两条命令。先找出哪些容器占用最多:

du -sh /var/lib/docker/containers/*/ | sort -rh | head -10

再用容器 ID 反查业务身份,确认是哪个服务在疯狂写日志:

docker inspect --format '{{.Name}} {{.LogPath}}' <容器ID>

膨胀速度可以粗略估算:假设某个容器每分钟打印 300 行日志、每行平均 200 字节,一天就是约 83MB,一个月约 2.5GB。一台跑着 10 个这类容器的宿主机,一个月仅容器日志就能吃掉 25GB 磁盘。如果磁盘本身不大,或者和其他服务共用一块盘,写满只是时间问题;磁盘写满之后,数据库写入失败、服务无法创建新文件等连锁故障会一起爆发。

日志文件增长示意

方案一:日志驱动内置轮转参数

json-file 驱动自带两个轮转参数:max-size 限制单个日志文件大小,max-file 限制保留的轮转文件数量。单个容器可以在启动时显式指定:

docker run -d \
  --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  nginx:stable

这样每个容器的日志最多占用 10m × 3 = 30MB,写满后最旧的文件被覆盖,磁盘占用从此有了硬上限。

如果容器数量多,逐个加参数不现实,可以在 /etc/docker/daemon.json 里做全局默认配置:

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

修改后重启 Docker 服务让配置生效:

systemctl restart docker

这里有一个关键限制必须记住:日志驱动参数在容器创建时固化,daemon.json 的修改只对之后新建的容器生效,存量容器不会自动获得轮转能力。要让老容器享受新配置,只能 docker compose up -d --force-recreate 之类的方式重建容器。如果你的服务用 Docker Compose(一种用 YAML 文件编排多个容器的工具)管理,可以直接在服务定义里写 logging 段,配置随代码走,迁移服务器时也不用重新调参。相关编排细节可以参考这篇 Docker Compose 多服务部署教程。

全局轮转配置示意

方案二:与 logrotate 联动清理存量日志

内置轮转解决了”以后不膨胀”,但处理不了”已经膨胀”的存量文件,也不适合那些不方便重建的老容器。这时候 logrotate(Linux 系统标准的日志轮转工具)就是最合适的补充——它能对已存在的日志文件做截断、压缩和定期清理,不需要动容器本身。

在 /etc/logrotate.d/ 下新建一个 docker-containers 配置文件:

/var/lib/docker/containers/*/*.log {
  rotate 5
  daily
  maxsize 50M
  compress
  missingok
  delaycompress
  copytruncate
  dateext
}

逐项解释关键参数:daily 每天检查一次;maxsize 50M 让超过 50MB 的文件在每天检查之外额外提前轮转;rotate 5 最多保留 5 份历史;compress 配合 delaycompress 把最近一份保持原样、更早的压缩成 gzip,通常能把日志总体积压到原来的 10% 左右;copytruncate 是整个配置的核心——它先把日志内容复制一份再原地清空原文件,容器的文件句柄始终指向同一个 inode,不需要重启或通知容器进程;missingok 允许某些容器日志暂时不存在时跳过而不报错。

配好之后不要等 cron(Linux 定时任务服务)到点才验证,先手动跑一轮看效果:

logrotate -d /etc/logrotate.d/docker-containers
logrotate -f /etc/logrotate.d/docker-containers

第一条 --debug 模式只打印将要执行的动作,第二条 --force 真正执行一次。执行完再用 du -sh /var/lib/docker/containers/*/ | sort -rh | head 复查,膨胀最严重的几个日志文件应该已经缩小。

logrotate 方案的边界也要说清楚:copytruncate 在复制和清空之间存在一个极短窗口,这期间容器新写入的少量日志行可能丢失。对绝大多数业务日志来说这个损耗可以忽略,但如果你在做审计级日志采集,应该用专门的日志收集器(如 Fluentd、Filebeat 这类把日志直接输出到远端的组件)而不是依赖宿主机文件轮转。

copytruncate 流程示意

两种方案对比与组合用法

两个方案不是二选一的关系,覆盖的场景不同。用一张表把差异摆清楚:

维度 日志驱动内置轮转 logrotate 联动
生效对象 仅新建容器 所有已存在的日志文件,含存量容器
配置位置 daemon.json 或 run 参数 /etc/logrotate.d/ 独立文件
需要重建容器 是(存量容器需重建) 否,宿主机层面直接处理
磁盘占用上限 max-size × max-file 硬上限 轮转+压缩后通常降至原始体积的 10%-20%
数据完整性 无丢失窗口 copytruncate 有极短丢失窗口

实际运维中最稳的组合是:新环境一律在 daemon.json 写好全局 max-size/max-file,从源头封住膨胀;宿主机再配一份 logrotate 兜底,处理历史遗留的大文件,同时压缩归档节省空间。两者叠加后,即使某个容器配置遗漏,日志体积也有第二道闸门。

对承载多个容器的长期项目,还有一个经验值可以参考:把单容器日志上限控制在 30-50MB(max-size=10m、max-file=3 到 5),一台跑 20 个容器的宿主机,容器日志总占用就能稳定在 1GB 以内,配合每周例行磁盘巡检足够安全。VPS(VPS,虚拟专用服务器)磁盘本身不大,这类容量治理尤其值得提前做,选购时也建议把磁盘余量纳入评估,可以参考这份 VPS 选购指南。

常见踩坑与排查清单

治理过程中有几个高频坑,逐一列出来对照检查。第一,du 显示日志文件缩小了但 df 磁盘占用没变——这通常是进程还握着已删除文件的句柄,lsof | grep deleted 能找到它们,重启对应容器即可释放。第二,改了 daemon.json 却发现老容器日志照旧膨胀,原因就是前面说的”参数在创建时固化”,必须重建容器才生效。第三,logrotate 报 log needs rotating 但什么都没做,检查一下 daily 与 maxsize 的组合语义:只有同时满足时间周期和大小条件,或配置了 minsize,才会按预期轮转。

还有一条容易忽略的防线:日志膨胀往往和异常日志风暴同时出现,比如某个应用进入重连循环后每秒打印几十条错误。轮转只是控制磁盘,根因还得靠日志内容本身发现。给宿主机配上磁盘空间告警(例如超过 80% 触发通知),能在日志写满磁盘之前给你留出处理窗口。系统层面的定时任务与日志排障思路,这篇 Linux 定时任务实战写得更细。

最后,如果你的容器跑在一台需要同时服务网站业务的服务器上,日志治理只是服务器稳定性的一环,Web 服务器自身的日志与缓存策略也要同步梳理,可参考这份 Nginx 性能调优清单。

总结与行动建议

容器日志膨胀的本质是”默认配置没有上限”,治理思路就是给它加上限、加周期、加压缩。建议按这个顺序行动:先用 du 命令盘点当前宿主机的容器日志占用,确认是否已经存在 GB 级文件;然后在 /etc/docker/daemon.json 写入 max-size 与 max-file,并对存量容器安排一次重建;再在 /etc/logrotate.d/ 落地 copytruncate 方案兜底,手动 logrotate -f 验证一轮;最后把磁盘使用率监控接上告警,防止同类问题在其他机器上重演。

如果你需要一台磁盘配额清晰、支持快照备份的运行环境来托管这批容器,Hostease 的 VPS(VPS,虚拟专用服务器)支持按需选择磁盘规格,配合本文的轮转策略可以长期把日志占用压在可控范围,欢迎了解 Hostease VPS 主机方案。

发表评论