核心问题:默认 json-file 驱动无日志轮转

  • 日志位置: /var/lib/docker/containers/<container-id>/<container-id>-json.log
  • 风险: 默认配置下,此日志文件会无限增长。若不干预,最终会耗尽磁盘空间(尤其是 /var 分区),导致容器或宿主机故障。
  • 表象: 出现 No space left on device 错误,服务不可用。使用 df -h 检查磁盘,常发现 /var/var/lib 占用率 100%。

解决方案核心:配置日志轮转 (Log Rotation)

主要针对最常用的 json-file 驱动。目标是限制单个日志文件大小和保留的历史文件数量。

配置方法 (三选一):

  1. docker run 启动时指定 (推荐:灵活控制)

    1
    2
    3
    4
    5
    6
    7
    docker run -d \
    --log-driver json-file \ # 通常可省略(默认)
    --log-opt max-size=10m \ # 单个日志文件最大大小(支持 k, m, g)
    --log-opt max-file=3 \ # 保留的旧日志文件最大数量(包含当前活跃文件)
    --log-opt compress=true \ # 可选:压缩轮转后的旧日志(gzip)
    --name my-container \
    your-image:tag
    • 总日志量估算: max-size * max-file (例如 10m * 3 ≈ 30MB)。
    • 轮转机制: 当前日志文件达到 max-size 时,会被重命名为 <container-id>-json.log.1 (之前的 .1 变为 .2,依此类推),并新建一个空日志文件。当文件数超过 max-file 时,最旧的日志文件 (.3) 被删除。
    • 优点: 按容器精细化管理策略。
  2. 修改 Docker Daemon 全局配置 (推荐:一劳永逸)

    • 编辑配置文件 /etc/docker/daemon.json (不存在则创建):
      1
      2
      3
      4
      5
      6
      7
      8
      {
      "log-driver": "json-file",
      "log-opts": {
      "max-size": "20m", // 全局默认单个文件大小
      "max-file": "5", // 全局默认保留文件数
      "compress": "true" // 可选:压缩旧日志
      }
      }
    • 保存文件,确保权限正确 (通常 root:root, 644)。
    • 重启 Docker 服务使配置生效:
      1
      sudo systemctl restart docker  # 或 sudo service docker restart
    • 重要:
      • 此配置仅对之后新创建的容器生效
      • 单个容器 docker run 时的 --log-opt 会覆盖此全局设置。
      • 重启 Docker 会短暂中断服务,请在维护窗口操作。
  3. 处理正在运行的容器 (临时/根治)

    • 临时清理 (应急,谨慎!):
      • 查找日志路径:docker inspect -f '{{.LogPath}}' <container-name-or-id>
      • 清空前务必确认: 最好先停止容器 (docker stop),避免日志写入冲突或丢失。
      • 清空文件 (两种方式):
        1
        2
        3
        4
        # 方法 1: Truncate (保留文件 inode,速度快)
        sudo truncate -s 0 $(docker inspect -f '{{.LogPath}}' <container-id>)
        # 方法 2: Echo (覆盖内容)
        sudo sh -c 'echo "" > $(docker inspect -f '{{.LogPath}}' <container-id>)'
      • 风险: 只是临时释放空间。如果容器持续输出日志,文件会再次增大。不清空源头(未配置轮转)问题会重现。
    • 根治方案 (推荐):重建容器
      1. 记录容器配置:使用 docker inspect 查看完整配置,或借助工具 runlike (docker run --rm -v /var/run/docker.sock:/var/run/docker.sock assaflavie/runlike <container-id>) 生成等效的 docker run 命令。
      2. 停止并删除旧容器:
        1
        2
        docker stop <container-id>
        docker rm <container-id>
      3. 使用记录的命令重新创建容器,并在 docker run 命令中加入 --log-opt max-size--log-opt max-file 参数。

其他日志驱动概览 (按需选择)

驱动名称 原理简述 主要优点 主要缺点/考量 适用场景
json-file 写日志到宿主机 JSON 文件 简单,docker logs 可用 必须手动配置轮转! 开发、测试、需 docker logs
journald 发送日志到宿主 Systemd Journal 集成系统日志,自带轮转管理 需 Systemd 系统,需学 journalctl Systemd Linux 宿主机
syslog 转发日志到 Syslog 服务器 集中收集,利用现有设施 需配置维护 Syslog 服务 集成到现有 Syslog 环境
fluentd
gelf
awslogs
splunk
发送到外部日志收集/分析平台 强大分析、存储、可视化;卸载本地存储 配置较复杂,依赖外部服务/网络 生产环境、大规模、云环境、需集中日志分析

配置建议与最佳实践

  1. 必须配置轮转: 无论使用哪种驱动(特别是 json-file),绝不能依赖默认的无限制设置
  2. json-file 轮转参数参考:
    • 开发环境: max-size=5m, max-file=2-3 (总量 ~10-15MB)
    • 测试环境: max-size=10m-20m, max-file=3-5 (总量 ~30-100MB)
    • 生产环境: max-size=50m-100m, max-file=5-10 (总量 ~250MB-1GB)。核心应用取高值。 强烈建议启用 compress: "true"
  3. 优先全局配置 (daemon.json): 设置合理的全局默认值 (json-file + max-size + max-file + compress),防止遗漏。这是最保险的方式。
  4. 按需覆盖: 对特殊需求的容器,在 docker rundocker-compose.yml 中覆盖全局默认值。
  5. docker-compose.yml 配置示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    services:
    my-service:
    image: your-image:tag
    logging:
    driver: json-file
    options:
    max-size: "50m"
    max-file: "5"
    compress: "true"
  6. 谨慎操作:
    • 避免 --log-driver=none 这会禁用 docker logs 和所有 stdout/stderr 捕获,极度不推荐,除非应用有完善的自定义日志机制。
    • 批量清理 (find ... -exec truncate ...) 仅用于紧急救援,且务必评估风险。 清空后必须立即配置轮转。
  7. 监控:
    • 监控宿主机关键分区(/, /var, /var/lib/docker)的磁盘使用率。
    • 设置磁盘空间告警阈值(如 80%)。
    • (可选) 监控重要容器日志文件大小。
  8. 驱动选择:
    • 中小规模/简单环境:json-file + 轮转 或 journald (Systemd 系统)。
    • 生产/大规模/云环境:强烈推荐 fluentd, gelf, awslogs 等驱动接入集中式日志平台 (ELK, Loki, Splunk, CloudWatch Logs 等),解决本地存储限制并提供强大分析能力。

总结:

Docker 默认日志配置存在磁盘耗尽风险。核心解决方案是为 json-file 驱动配置 max-sizemax-file 日志轮转。最佳实践是修改 /etc/docker/daemon.json 设置全局默认轮转参数,并根据需要为特定容器覆盖配置。对于已存在的“日志大户”,重建容器是根治方案。生产环境应优先考虑将日志发送到集中式管理平台。定期检查磁盘和日志配置是维护健康 Docker 环境的关键步骤。