Docker日志管理:防止容器把磁盘撑爆

Docker日志管理:防止容器把磁盘撑爆

你的服务器磁盘又满了。df -h一看,/var/lib/docker占了80GB。你进去翻,发现是容器日志。

一个容器一天写几个GB日志,很正常。跑了几个月的容器,日志文件可能几十GB。Docker默认不限制日志大小,不自动清理。你不删,它就一直长。

今天聊几个方法,让Docker日志不再撑爆磁盘。


先看一个数据

某云厂商统计,超过30%的容器环境磁盘爆满,元凶是容器日志。一个高并发的Nginx容器,access日志一天能写5-10GB。跑一个月,300GB。如果你不清理,它会把整个磁盘塞满。

Docker默认的日志驱动是json-file,所有容器的标准输出和标准错误都被JSON格式记录,存在宿主机的/var/lib/docker/containers/目录下。文件不轮转,不压缩,不删除。


第一步:查看当前日志占用

bash

# 查看Docker目录大小
du -sh /var/lib/docker

# 找到日志文件位置
find /var/lib/docker/containers/ -name "*.log" -exec ls -lh {} \;

# 按大小排序
find /var/lib/docker/containers/ -name "*.log" -exec du -sh {} \; | sort -hr | head -10

你会看到最大的几个日志文件,几十GB都有可能。


第二步:清理现有日志

方法一:truncate(不删文件,只清空内容)

bash

# 找到容器ID
docker ps

# 清空该容器的日志文件
truncate -s 0 /var/lib/docker/containers/容器ID/容器ID-json.log

方法二:docker logs配合重定向

bash

docker logs 容器名 > /dev/null 2>&1

有些版本的Docker,这样做不会真正释放磁盘空间,只是清空输出缓冲。推荐用truncate

方法三:重启容器

bash

docker restart 容器名

重启后Docker会新建日志文件,但旧文件还在。需要手动删旧文件。

注意:正在写的日志文件,删除后Docker不会立即释放磁盘空间,因为文件句柄还在。需要重启容器或truncate


第三步:配置日志轮转

不要手动清理,让Docker自己管。

编辑/etc/docker/daemon.json(没有就创建):

json

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  }
}
  • max-size=100m:单个日志文件最大100MB
  • max-file=3:最多保留3个文件

一个容器最多300MB日志。超过后,Docker自动轮转:删除最旧的,新建当前的。

重启Docker服务使配置生效:

bash

systemctl restart docker

已存在的容器不会自动应用新配置,需要重建:

bash

docker-compose down
docker-compose up -d

指定单个容器的日志限制(不修改全局配置):

bash

docker run -d --log-opt max-size=100m --log-opt max-file=3 镜像名

或在docker-compose.yml里:

yaml

services:
  aimage: nginx
    logging:
      driver: json-file
      options:
        max-size: 100m
        max-file: "3"

第四步:使用journald驱动

如果你的系统用systemd,可以用journald接管Docker日志。journald本身就支持轮转和大小限制。

/etc/docker/daemon.json里改成:

json

{
  "log-driver": "journald"
}

重启Docker。查看日志:

bash

journalctl -u docker CONTAINER_NAME=容器名

journald的大小限制在/etc/systemd/journald.conf里配置:

ini

SystemMaxUse=5G
MaxFileSec=1week

第五步:日志输出重定向到/dev/null

某些容器的日志对你没用(比如健康检查的ping、监控探针)。可以直接丢掉,不写磁盘。

Docker Compose里:

yaml

services:
  aimage: nginx
    logging:
      driver: "none"

或运行时加--log-driver=none。但这样的话,出问题时没有日志可查,不推荐在生产环境用,只在彻底不需要日志的场景使用。


第六步:外部日志收集

只限制大小、保留几天还不够。生产环境需要把日志发到集中式日志系统(ELK、Loki、Splunk)。

/etc/docker/daemon.json配置远程日志驱动:

json

{
  "log-driver": "syslog",
  "log-opts": {
    "syslog-address": "udp://192.168.1.100:514"
  }
}

或使用第三方日志驱动(如Loki的Docker插件)。这样日志在容器本地不大量留存,统一送到日志服务器,持久化、可搜索、可告警。


临时清理脚本

如果你不想配置,只想手动清理:

bash

#!/bin/bash
# 清理所有容器日志(危险,确保不需要旧日志时再执行)
for container in $(docker ps -aq); do
    log_file="/var/lib/docker/containers/$container/$container-json.log"
    if [ -f "$log_file" ]; then
        truncate -s 0 "$log_file"
        echo "清空: $container"
    fi
done

保存为clean_docker_logs.sh,执行chmod +x后运行。危险:会清空所有容器的日志,不可恢复。确保你不需要这些日志再跑。

推荐做法是配置轮转,让系统自动化,不需要手动清理。


真实案例

一台跑着20个容器的服务器,磁盘突然写满。排查发现,其中一个Java容器开启了DEBUG日志,每天写50GB。日志轮转没配置,跑了半个月,750GB日志占满磁盘。

运维改了daemon.json,设置max-size=100m,重启容器。新日志自动轮转,旧日志清理后,磁盘使用从800GB降到100GB。加了一条告警规则:磁盘使用率超过80%自动通知。


最后一句

Docker容器日志默认不轮转,不限制,不清理。你不管它,它迟早撑爆你的磁盘。

配置daemon.json,设个max-sizemax-file,5分钟的事。一劳永逸。

如果日志真的很重要,别让它只留在容器本地。发到ELK或Loki,集中存储,集中查询。

磁盘满了再清理,是救火。提前配置轮转,是防火。选哪个,你自己决定。

知识库

数据库主从复制:MySQL读写分离实战

2026-5-28 16:12:01

知识库

GitHub Actions入门:代码推送自动部署到服务器

2026-5-29 16:11:58

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧