Docker Compose 如何配置日志驱动 json-file 限制大小

文章导读
Docker 容器跑久了,日志文件增长是最常见的磁盘占用来源之一。json-file 是 Docker 默认的日志驱动,但在默认配置下它不做任何大小限制,日志会一直写进宿主机的 /var/lib/docker/containers/... 目录。如果用了 Docker Compose 管理服务,通常不需要也没必要去改整个 Docker 守护进程的默认配置,直接在 Compose 文件里给服务指定
📋 目录
  1. A 先判断日志是不是落在 json-file
  2. B 在服务里单独指定 logging,不影响其他容器
  3. C max-size 和 max-file 要一起设置
  4. D 改完怎么确认生效
  5. E 已有的日志不会自动消失
  6. F 多个服务不要重复写配置
A A

Docker 容器跑久了,日志文件增长是最常见的磁盘占用来源之一。json-file 是 Docker 默认的日志驱动,但在默认配置下它不做任何大小限制,日志会一直写进宿主机的 /var/lib/docker/containers/... 目录。如果用了 Docker Compose 管理服务,通常不需要也没必要去改整个 Docker 守护进程的默认配置,直接在 Compose 文件里给服务指定 json-file 的轮转参数就够了。不过动手之前要先想清楚一个限制:这个配置不是对已有容器即时生效的,改动后需要重建容器才行。

先判断日志是不是落在 json-file

在改配置前,先确认一下现在的容器用的是不是 json-file。可以执行 docker inspect <容器名>,看 LogConfig 字段。如果输出中 Type 不是 json-file,那么即使 Compose 里写了 driver: json-file,容器重建后才会切换。同时还要注意,LogConfig 里的 Config 是空的,说明当前没有大小限制。默认情况下,json-file 驱动不会自动轮转,日志文件会一直增长,直到磁盘满。所以这是一个潜在风险,尤其日志量大的服务。

在服务里单独指定 logging,不影响其他容器

在 docker-compose.yml 中,每个服务都可以单独指定 logging 配置。为了让 json-file 驱动限制日志文件大小,需要在服务的 logging 节点下设置 driver: json-file,并在 options 中指定 max-size 和 max-file。例如 max-size: "10m",max-file: "3",表示单个日志文件达到 10 MB 时触发轮转,最多保留 3 个日志文件。注意,这个配置在容器重新创建时才生效,修改 YAML 后仅执行 docker-compose up -d 可能不会更新已经运行的容器,必要时需要 docker-compose up -d --force-recreate。

这种方式的好处是只影响被配置的服务,不会动其他容器,也不需要重启 Docker 守护进程。如果你只想控制某一个日志量特别大的服务,这个做法最直接。

max-size 和 max-file 要一起设置

max-size 是触发日志轮转的阈值,写法可以带上单位 k、m、g,比如 5m 代表 5 MB。max-file 控制保留的日志文件数量,默认值为 1,也就是说如果只设置 max-size 而不设置 max-file,那么轮转后旧文件很快会被删除,无法追溯历史日志。建议至少把 max-file 改为 3 或更大,同时可以加上 compress: true,对轮转后的文件进行压缩,减少磁盘占用。但这个 compress 选项不是必须的,需要根据实际存储空间权衡。

具体 max-size 设多大,要看单个容器一天写多少日志,然后倒推保留几份能撑多久。不要盲目设一个很小的值,比如 1m,可能导致日志写得很频繁,CPU 和磁盘 IO 反而增加。可以先设一个保守值,观察一天再调整。

改完怎么确认生效

容器启动后,可以用 docker inspect 检查日志配置是否生效。查看输出中的 LogConfig 字段,Type 应该是 json-file,Config 里面要包含 max-size 和 max-file。如果两个值都正确,说明 Compose 中的配置已经应用到容器。也可以用 docker logs 观察当前输出,但 docker logs 看到的内容不包含被轮转掉的旧文件。要查看宿主机上的实际日志文件,可以进入 Docker 数据目录,默认路径是 /var/lib/docker/containers//-json.log,如果目录下有多个被轮转的文件,说明 max-file 生效了。

Docker Compose 如何配置日志驱动 json-file 限制大小

路径中的两个斜杠之间需要替换成容器的完整 ID,可以用 docker ps --no-trunc 查到。另外,直接执行下面的命令,可以只把日志配置以 JSON 格式打出来,方便确认参数是否写入:

docker inspect --format '{{json .HostConfig.LogConfig}}' <容器名>

已有的日志不会自动消失

最常见的坑是修改 max-size 后,现有容器不会自动截断已有日志。日志文件只有在下一次写入时超出 max-size 才会触发轮转,所以原来已经很大的日志文件不会被压缩或删除。另一种情况是只给某个服务配置了 logging,而其他服务仍然使用 Docker 守护进程的默认日志驱动,最终所有容器加起来产生的日志量仍然可能占满磁盘。建议在项目层面统一规划日志配置,要么在所有服务上显式设置,要么通过 daemon.json 设置全局限额。

如果某个日志文件已经很大,你想立即释放磁盘,可以先确认容器不需要旧日志后,使用 truncate -s 0 清空该文件。但这样做不会改变容器的文件描述符,一般可以继续写。更安全的做法是重建容器,让新配置从头开始写日志。在清空或删日志前,建议先确认没有其他进程在读取这个文件。

多个服务不要重复写配置

如果一个 Compose 项目里有多个服务,重复书写 logging 配置容易出错。可以在文件顶部定义一个 YAML 扩展字段,比如 x-logging,然后在每个服务里复用。这样做的好处是,将来调整 max-size 或 max-file 时,只需要改一处。示例配置如下:

version: "3.8"
x-logging: &default-logging
  driver: json-file
  options:
    max-size: "10m"
    max-file: "3"
    compress: "true"
services:
  app:
    image: nginx
    logging: *default-logging
  worker:
    image: busybox
    logging: *default-logging

注意,YAML 的 options 里的值都会作为字符串传给 Docker,所以 compress 写成 "true" 是常见的写法。修改后要让所有服务生效,同样需要 docker-compose up -d --force-recreate。

配置 json-file 的 max-size 和 max-file,是控制容器日志体积最直接的办法。但真正的关键不在写多少配置,而在改完之后一定重建容器,并且用 docker inspect 确认 LogConfig 里真的带上了参数。如果日志量还在增长,不要急着把 max-size 改小,先看下是哪些服务写得多,再决定要不要调大 max-file 或压缩旧日志。项目里多个服务最好统一规划,避免个别服务漏掉造成磁盘告警。