
你的服务器磁盘又满了。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:单个日志文件最大100MBmax-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-size和max-file,5分钟的事。一劳永逸。
如果日志真的很重要,别让它只留在容器本地。发到ELK或Loki,集中存储,集中查询。
磁盘满了再清理,是救火。提前配置轮转,是防火。选哪个,你自己决定。




