Docker 容器日志写满磁盘:json-file 限制与 max-size 配置

    发布时间:2026-09-20 04:30 更新时间:2026-09-20 04:30 阅读量:0

    很多站长第一次遇到 Docker 相关的磁盘告警,都是同一种场景:服务器上跑着几个容器,业务本身没写什么大文件,某天却收到系统盘使用率超过 90% 的提醒。登进去用 du -sh /var/lib/docker/* 一层层看下去,最后发现空间全被 /var/lib/docker/containers/ 下面的日志文件吃掉了。这篇就把这件事讲清楚:默认行为是什么、为什么它会无限增长、以及怎么用配置把它限制在合理范围内。

    默认的 json-file 驱动:日志不会自己消失

    Docker 默认使用 json-file 日志驱动。容器里进程写到标准输出(stdout)和标准错误(stderr)的内容,都会被 Docker 收集起来,按 JSON 格式落盘,路径大致是 /var/lib/docker/containers/<容器ID>/<容器ID>-json.log。这个文件的结构是一行一个 JSON 对象,记录了时间戳、输出流类型和日志内容。

    关键点在于:json-file 驱动默认不做任何轮转和容量限制。也就是说,只要容器还在运行、还在往 stdout 打日志,这个文件就会一直追加下去。程序员在代码里 print、console.log,或者 Nginx、PHP-FPM、Java 应用把访问日志、异常堆栈打到控制台,最终都会落到这个文件上。一个请求量稍大的站点,每天产生几百 MB 甚至几 GB 的容器日志并不罕见,跑几周就能把一块 40G 的系统盘填满。

    更麻烦的是,磁盘写满之后不只是 Docker 出问题:系统日志写不进去、MySQL 可能拒绝写入、SSH 登录都可能受影响。所以这件事最好在部署阶段就配好,而不是等告警了再救火。

    在 daemon.json 里做全局限制

    推荐的做法是修改 Docker 守护进程配置,让所有新建容器默认带上日志限制。配置文件是 /etc/docker/daemon.json,如果文件不存在就新建一个,写入下面的内容:

    {
      "log-driver": "json-file",
      "log-opts": {
        "max-size": "100m",
        "max-file": "5"
      }
    }
    

    两个参数的含义很直白:max-size 表示单个日志文件达到多大就轮转,这里设成 100MB;max-file 表示最多保留几个轮转文件,这里保留 5 个。两者相乘,单个容器最多占用约 500MB 的日志空间,超过之后最旧的日志文件会被删除。这个量级对多数中小型站点够用,你可以按磁盘容量和日志价值自行调整,比如日志量大就设 max-size: 50m、max-file: 3。

    写完配置后需要重启 Docker 生效。重启会短暂中断所有容器(除非配置了 live-restore),生产环境建议安排在维护窗口:

    sudo systemctl daemon-reload
    sudo systemctl restart docker
    sudo systemctl status docker --no-pager
    

    这里有个容易踩的坑:daemon.json 的日志配置只对新建的容器生效,已经在跑的容器不会自动应用。想让老容器也受限,需要把它们重建一次,比如用 docker compose up -d --force-recreate,或者先 docker rm -f 再用原命令重新跑。另外,如果 daemon.json 里 JSON 格式写错,Docker 会启动失败,改完记得用 docker info 确认服务正常、日志驱动确实是 json-file。

    单容器覆盖与验证清理

    不是所有日志都值得长期保留,某些调试用的容器可能只想留很少的量。这时可以在启动参数或 Compose 文件里单独指定,覆盖全局默认值。命令行写法:

    docker run -d \
      --name web-demo \
      --log-driver json-file \
      --log-opt max-size=10m \
      --log-opt max-file=2 \
      nginx:stable
    

    如果用 Docker Compose,则在服务下加一段 logging 配置,效果一样:

    services:
      web:
        image: nginx:stable
        logging:
          driver: json-file
          options:
            max-size: "10m"
            max-file: "2"
    

    配置完之后,怎么确认真的生效了?可以先看某个容器的日志文件大小,再对比配置值。查看容器日志路径和大小:

    docker inspect --format '{{.LogPath}}' web-demo
    sudo ls -lh /var/lib/docker/containers/<容器ID>/ | grep json.log
    

    如果看到 -json.log 之外还出现了 -json.log.1、-json.log.2 这类文件,说明轮转已经在工作。反过来,如果单个 log 文件一直涨、始终没有带序号的文件出现,那多半是配置没吃上,回去检查容器是不是在改配置之前创建的。

    对于已经被写满的机器,先救急再治本。可以用下面的命令查看各容器日志占用,找出最大的那个:

    sudo du -sh /var/lib/docker/containers/*/*-json.log | sort -h | tail -n 10
    

    注意不要直接 rm 正在写入的日志文件。虽然删除后空间会被释放(因为文件句柄仍被占用,和之前讲过的"删了文件空间不释放"是同一类现象),但 Docker 对日志文件的偏移量记录可能错乱,后续日志行为不可预期。更稳妥的做法是先把容器停掉、清理日志,再按上面的方式加上限制后重启;或者用 truncate -s 0 把文件清空(具体效果以你的 Docker 版本和实际环境为准,建议先在测试机验证)。

    小结与下一步

    容器日志写满磁盘,根因通常不是日志本身有问题,而是默认配置没有上限。把 daemon.json 里的 max-size 和 max-file 配上,是成本最低的一道防线;对日志量特别大的服务,再单独覆盖更小的值。配置生效后,建议顺手做两件事:一是把 df -h 和日志目录大小加入日常巡检,二是评估是否需要把日志集中收集到外部系统,本地只留短期缓冲。磁盘空间这件事,永远是提前配好参数,比事后登机救火轻松得多。

    继续阅读

    📑 📅
    Nginx 与后端长连接调优:keepalive 与 upstream 复用 2026-09-20
    Docker 容器内 CPU 被限流排查:cfs_quota、cpuset 与 top 显示异常 2026-09-19
    Nginx gzip 与 Brotli 压缩配置实战:静态资源体积优化 2026-09-19
    PHP-FPM 进程数怎么调:pm.max_children 与内存估算 2026-09-19
    Docker容器DNS解析异常排查:resolv.conf与自定义网络 2026-09-19
    Linux时间与时区排查:date、timedatectl与容器时区一致性 2026-09-20
    服务器网卡多队列与中断绑定入门:RPS、RSS 与 irqbalance 怎么取舍 2026-09-20
    Nginx 上传大文件报 413 与超时:参数与缓冲区排查 2026-09-20
    Docker容器缺命令:精简镜像补装与临时容器调试 2026-09-20
    Nginx location 匹配优先级实战:=、^~、~ 命中顺序验证 2026-09-21