一、为什么容器日志会撑爆磁盘?

想象一下你家的垃圾桶。如果从来不倒垃圾,总有一天会把厨房塞满。Docker容器也是这样,默认情况下它会把所有日志都堆在主机的一个文件里,特别是像Java应用这种话痨,几天就能生成几个G的日志文件。

常见症状包括:

  • 服务器突然报"磁盘空间不足"
  • df -h命令显示/var/lib/docker目录异常膨胀
  • 容器莫名其妙被OOM(内存不足)杀死

二、Docker自带的日志限制

Docker其实自带了简易的日志控制功能,就像给垃圾桶加了个盖子。在运行容器时可以通过参数控制:

# 技术栈:Docker
# 限制单个日志文件100MB,最多保留3个旧日志
docker run --log-opt max-size=100m --log-opt max-file=3 nginx

参数解释:

  • max-size:单个日志文件的最大值,到达后自动分割
  • max-file:保留的旧日志文件数量,超出会自动删除最老的

但这种方式有两个不足:

  1. 不能按时间轮转(比如每天自动分割)
  2. 所有容器需要单独配置

三、使用logrotate专业方案

Linux自带的logrotate才是真正的"智能垃圾桶管理系统",它能:

  • 按时间或大小轮转
  • 压缩旧日志节省空间
  • 通过cron定时任务自动运行

3.1 配置Docker全局日志策略

# 技术栈:Docker + Linux
# 创建专用配置文件
sudo tee /etc/logrotate.d/docker <<'EOF'
/var/lib/docker/containers/*/*.log {
    # 每天轮转一次
    daily
    # 保留最近7天的日志
    rotate 7
    # 轮转后延迟压缩(避免影响正在写的日志)
    delaycompress
    # 使用gzip压缩旧日志
    compress
    # 如果日志缺失也不报错
    missingok
    # 轮转后创建新空日志文件
    create
    # 文件大于100M也触发轮转
    size 100M
}
EOF

3.2 手动测试配置

# 强制立即执行轮转测试
sudo logrotate -vf /etc/logrotate.d/docker

你会看到类似这样的输出:

reading config file /etc/logrotate.d/docker
Handling 18 logs
rotating /var/lib/docker/containers/abcd1234/abcd1234-json.log

四、进阶技巧与注意事项

4.1 容器运行时日志驱动选择

Docker支持多种日志输出方式,就像不同的垃圾处理方式:

# 使用系统日志工具(syslog)接管
docker run --log-driver=syslog nginx

# 直接禁用容器日志(极端情况使用)
docker run --log-driver=none alpine

4.2 容器内应用日志的最佳实践

聪明的应用应该自己管理日志:

// 技术栈:Java + Logback
// 在logback.xml中配置滚动策略
<configuration>
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>/logs/app.log</file>
        <!-- 按日期和大小滚动 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 每天滚动 -->
            <fileNamePattern>/logs/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 单个文件最大100MB -->
            <maxFileSize>100MB</maxFileSize>
            <!-- 保留30天 -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>
</configuration>

4.3 注意事项清单

  1. 监控报警:即使有轮转也要监控磁盘使用率
  2. 日志分级:生产环境建议关闭DEBUG日志
  3. 集中收集:考虑ELK等方案集中管理日志
  4. 特殊容器:数据库类容器要特别小心日志配置

五、方案对比与选择建议

方案 优点 缺点 适用场景
Docker原生配置 简单直接 功能有限 开发测试环境
logrotate 功能全面 需要额外配置 生产环境物理机
应用自身管理 最精准控制 需要改应用代码 可控的自研应用

对于大多数场景,我推荐组合方案:

  1. 使用logrotate作为最后防线
  2. 重要容器单独配置Docker日志参数
  3. 关键业务应用实现自己的日志管理

六、遇到问题怎么排查?

如果配置后日志还是疯涨,可以这样排查:

  1. 先找大文件:
sudo du -h /var/lib/docker | sort -rh | head -n 20
  1. 检查logrotate是否正常执行:
# 查看最后一次执行时间
grep docker /var/lib/logrotate/status
  1. 检查容器日志驱动:
docker inspect --format='{{.HostConfig.LogConfig.Type}}' 容器名

记住,好的日志管理就像定期打扫房间,既不能完全不管,也不必过度清洁。找到适合你业务节奏的平衡点最重要。