Docker 容器日志文件过大占用磁盘怎么配置 logrotate 轮转策略

文章导读
最稳妥的方案是直接配置 Docker 自带的日志轮转选项(max-size 和 max-file),而不是依赖系统的 logrotate 工具去切割 Docker 管理的日志文件。
📋 目录
  1. 为什么不建议直接用 logrotate
  2. 方案一:配置全局日志轮转(推荐)
  3. 方案二:针对单个容器配置
  4. 备选方案:强制使用 logrotate(高风险)
  5. 怎么验证是否生效
  6. 清理旧日志文件
  7. 常见坑
A A

Docker 容器日志过大占用磁盘?推荐原生配置而非 logrotate

最稳妥的方案是直接配置 Docker 自带的日志轮转选项(max-size 和 max-file),而不是依赖系统的 logrotate 工具去切割 Docker 管理的日志文件。

先说结论:优先修改 Docker 守护进程配置或容器启动参数,让 Docker 自己管理日志大小。

  • 适合:所有使用默认 json-file 日志驱动的 Docker 环境
  • 先准备:备份 daemon.json 文件,确认当前磁盘占用情况
  • 验收:检查日志文件是否按预期轮转,磁盘空间不再持续增长

为什么不建议直接用 logrotate

Docker 默认使用 json-file 日志驱动,守护进程会持有日志文件的句柄。如果使用系统 logrotate 直接切割(move/rename),Docker 进程可能仍然向旧文件句柄写入数据,导致日志丢失或磁盘空间无法释放。官方推荐的方式是通过 Docker 自身的 logging options 来控制。

方案一:配置全局日志轮转(推荐)

修改 Docker 守护进程配置,对所有新创建的容器生效。

1. 编辑配置文件

编辑 /etc/docker/daemon.json。如果文件不存在则新建,注意如果文件中已有其他配置,需合并 JSON 格式,避免语法错误:

sudo vim /etc/docker/daemon.json

写入以下内容:

Docker 容器日志文件过大占用磁盘怎么配置 logrotate 轮转策略
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

2. 重启 Docker 服务

警告:此操作会重启 Docker 服务,导致所有运行中的容器短暂中断。请在业务低峰期操作。

sudo systemctl daemon-reload
sudo systemctl restart docker

方案二:针对单个容器配置

如果不想影响所有容器,可以在启动容器时添加参数。注意:此配置仅对新建容器生效,现有容器通常需要重建才能应用。

docker run -d `--log-opt` max-size=10m `--log-opt` max-file=3 nginx

备选方案:强制使用 logrotate(高风险)

如果因合规等原因必须使用 logrotate,需配置 copytruncate 模式,但仍存在切割瞬间日志丢失的风险。

创建配置文件 /etc/logrotate.d/docker-containers

/var/lib/docker/containers/*/*.log {
    copytruncate
    daily
    rotate 3
    compress
    missingok
    notifempty
}

风险提示:copytruncate 会在复制后清空原文件,但复制和清空之间存在时间窗口,此期间的日志可能丢失。且 Docker 可能因文件 inode 变化出现异常。除非必要,否则不建议使用。

怎么验证是否生效

1. 检查文件数量

Docker 容器日志文件过大占用磁盘怎么配置 logrotate 轮转策略

进入容器日志目录,观察日志文件是否维持在设定数量内(例如 max-file 为 3,则最多看到 3 个文件):

ls -lh /var/lib/docker/containers/<容器 ID>/*.log

2. 检查容器配置

使用 inspect 命令确认容器的 LogPath 和配置是否生效:

docker inspect <容器 ID> | grep -A 10 LogPath

3. 观察磁盘空间

运行一段时间后,再次使用 df 或 du 命令确认磁盘空间不再异常增长。

清理旧日志文件

配置生效后,只会限制新生成的日志,已有的超大日志文件需要手动清理。

# 查找大于 100M 的日志文件
find /var/lib/docker/containers/ -name "*.log" -size +100M

# 手动清理前请确认业务无需保留,或先备份
# sudo rm /path/to/old.log

常见坑

  • daemon.json 语法错误:JSON 格式严格,多一个逗号或少一个括号都会导致 Docker 无法启动,修改前务必备份。
  • 重启影响业务:修改全局配置需要重启 Docker 服务,会导致所有容器短暂中断,建议在业务低峰期操作。
  • 旧日志不会自动清理:配置生效后,只会限制新生成的日志,已有的超大日志文件需要手动清理或等待轮转覆盖。
  • 不要混用策略:除非你非常清楚如何配置 copytruncate,否则不要同时使用系统 logrotate 和 Docker 自带轮转,避免冲突。