Docker 容器日志占用了我所有的磁盘空间

Posted

技术标签:

【中文标题】Docker 容器日志占用了我所有的磁盘空间【英文标题】:Docker container logs taking all my disk space 【发布时间】:2015-10-28 01:21:42 【问题描述】:

我在虚拟机上运行一个容器。我的容器默认将日志写入 /var/lib/docker/containers/CONTAINER_ID/CONTAINER_ID-json.log 文件,直到磁盘已满。

目前,我必须手动删除此文件以避免磁盘已满。我读到在 Docker 1.8 中会有一个rotate the logs 的参数。 您会推荐什么作为当前的解决方法?

【问题讨论】:

作为当前的解决方法,如果日志对您不重要,您可以完全关闭它。这可以通过使用--log-driver=none 启动 docker 守护进程来完成。如果您只想禁用特定容器的日志,您可以在docker run 命令中使用--log-driver=none 启动它们。另一种选择可能是将外部存储安装到/var/lib/docker。例如 NFS 共享或存储容量比相关主机更大的东西。 或使用journald 日志驱动程序,并记录日志轮换问题。 @Dharmit 它在 CoreOs 上的什么位置? @larsks 如何在 CoreOS 上做到这一点?似乎已安装 journald 并在 /var/log/journal 中生成日志,但我也登录 /var/lib/docker/containers/CONTAINER_ID/CONTAINER_ID-json.log @poiuytrez 什么在哪里?如果您愿意使用建议的选项启动 Docker 守护程序,/usr/lib/systemd/system/docker.service 可能是该文件。我不确定CoreOS。在 CentOS 上,这就是位置。至于其他问题,您需要更改 Docker 守护程序的选项以使用 journald 作为日志记录驱动程序。然后它将使用 journald 记录容器,而不是记录到 /var/lib/docker/containers/CONTAINER_ID/CONTAINER_ID-json.log。如果我遗漏了什么,@larsks 纠正我。 【参考方案1】:

Docker 1.8 已发布,带有日志轮换选项。添加:

--log-opt max-size=50m 

当容器启动时就可以了。您可以在以下位置了解更多信息: https://docs.docker.com/engine/admin/logging/overview/

【讨论】:

请注意,这似乎仅适用于 JSON 和流利的日志。 请注意,Docker 1.13 之后版本控制方案发生了变化。如果您的版本号类似于 17.03.0-ce,则表示您使用的是新的 1.13 后版本控制方案。 只知道 docker 会进行日志轮换是一个有用的事实【参考方案2】:

注意:这仅适用于 docker-compose 版本 2

例子:

version: '2'
services:
  db:
    container_name: db
    image: mysql:5.7
    ports:
      - 3306:3306
    logging:
      options:
        max-size: 50m

【讨论】:

使用此日志记录部分重新启动我的服务有效,但似乎没有任何效果,json 日志文件像以前一样继续增长... 第 3 版见 docs.docker.com/compose/compose-file/#logging【参考方案3】:

[这个答案涵盖了当前版本的 docker,供那些在被问到问题很久后遇到问题的人使用。]

要为所有新创建的容器设置默认日志限制,您可以在 /etc/docker/daemon.json 中添加以下内容:


  "log-driver": "json-file",
  "log-opts": "max-size": "10m", "max-file": "3"

如果您使用的是 systemd,则使用 systemctl reload docker 重新加载 docker(否则使用适当的重新启动命令进行安装)。

您也可以使用类似文件切换到本地日志记录驱动程序:


  "log-driver": "local",
  "log-opts": "max-size": "10m", "max-file": "3"

本地日志驱动程序以内部格式(我相信 protobufs)存储日志内容,因此您将在相同大小的日志文件中获得更多日志内容(或为相同的日志占用更少的文件空间)。本地驱动程序的缺点是日志转发器等外部工具可能无法解析原始日志。请注意,docker logs 仅在日志驱动程序设置为 json-filelocaljournald 时有效。

max-size 是对 docker 日志文件的限制,因此它包括 json 或本地日志格式化开销。 max-file 是 docker 将维护的日志文件的数量。一个文件达到大小限制后,将轮换日志,并在您超过max-file 时删除最旧的日志。

有关更多详细信息,docker 在以下位置提供有关所有驱动程序的文档:https://docs.docker.com/config/containers/logging/configure/

我也有一个关于这个主题的演讲。使用P查看演示者备注:https://sudo-bmitch.github.io/presentations/dc2019/tips-and-tricks-of-the-captains.html#logs

【讨论】:

【参考方案4】:

注意:这篇文章与 docker 版本 --log-opt 选项)

为什么不使用 logrotate(它也支持压缩)?

/var/lib/docker/containers/*/*-json.log 
hourly
rotate 48
compress
dateext
copytruncate

直接在您的 CoreOs 节点上配置它或部署一个容器(例如 https://github.com/tutumcloud/logrotate),该容器安装 /var/lib/docker 以轮换日志。

【讨论】:

我认为这不是一个好的解决方案。您需要反弹正在运行的任何守护程序以停止写入旧日志并开始写入新日志。否则,Linux 内核将继续引用内存中的旧日志文件(相对于磁盘而言)。 Logrotate 可以用普通的守护进程做到这一点,但弹跳 Docker 或容器会导致停机。 好点,我同意。这个答案是在 Docker (tm) 的早期提供的,同时构建的功能(如另一个答案中提到的)应该可以完成这项工作。 这有一些问题,它会旋转日志,但磁盘消耗仍然显示相似。我使用的是 v5.0.2,然后必须使用 get.docker.com 脚本将其升级到最新版本,才能在 docker create 或 run 命令中使用 --log-opt 选项。 @dman copytruncate 模式是否消除了反弹进程的必要性?【参考方案5】:

在运行容器时传递日志选项。一个例子如下

sudo docker run -ti --name visruth-cv-container  --log-opt max-size=5m --log-opt max-file=10 ubuntu /bin/bash

其中--log-opt max-size=5m 指定最大日志文件大小为 5MB,--log-opt max-file=10 指定最大轮换文件数。

【讨论】:

【参考方案6】:

使用 compose 3.9,您可以如下设置日志限制 H2>
version: "3.9"
services:
  some-service:
    image: some-service
    logging:
      driver: "json-file"
      options:
        max-size: "200k"
        max-file: "10"

上面显示的示例将存储日志文件,直到它们达到 200kB 的最大大小,然后旋转它们。存储的单个日志文件的数量由 max-file 值指定。随着日志增长超过最大限制,旧的日志文件将被删除以允许存储新日志。

可用的日志记录选项取决于您使用的日志记录驱动程序

controlling log files and sizes 的上述示例使用特定于json-file driver 的选项。这些特定选项在其他日志记录驱动程序上不可用。有关受支持的日志记录驱动程序及其选项的完整列表,请参阅日志记录驱动程序文档。

注意:只有 json-filejournald 驱动程序可以直接从 docker-compose up 和 docker-compose 日志中获取日志。使用任何其他驱动程序不会打印任何日志。

来源:https://docs.docker.com/compose/compose-file/compose-file-v3/

【讨论】:

【参考方案7】:

docker-compose 版本 1 的示例:

mongo:
  image: mongo:3.6.16
  restart: unless-stopped
  log_opt:
    max-size: 1m
    max-file: "10"

【讨论】:

【参考方案8】:

以防您无法停止容器,我创建了一个执行以下操作的脚本(您必须使用 sudo 运行它):

    创建一个文件夹来存储压缩日志文件作为备份。 查找正在运行的容器的 ID(由容器的名称指定)。 使用随机名称将容器的日志文件复制到新位置(步骤 1 中的文件夹)。 压缩之前的日志文件(以节省空间)。 按照您可以定义的特定大小截断容器的日志文件。

注意事项:

它使用 shuf 命令。确保您的 linux 发行版具有它或将其更改为另一个支持 bash 的随机生成器。 使用前,更改变量CONTAINER_NAME 以匹配您正在运行的容器;它可以是部分名称(不必是完全匹配的名称)。 默认情况下,它将日志文件截断为 10M(10 兆字节),但您可以通过修改变量 SIZE_TO_TRUNCATE 来更改此大小。 它在路径中创建一个文件夹:/opt/your-container-name/logs,如果您想将压缩日志存储在其他地方,只需更改变量LOG_FOLDER强>。 在生产中运行之前运行一些测试。
#!/bin/bash
set -ex

############################# Main Variables Definition:
CONTAINER_NAME="your-container-name"
SIZE_TO_TRUNCATE="10M"

############################# Other Variables Definition:
CURRENT_DATE=$(date "+%d-%b-%Y-%H-%M-%S")
RANDOM_VALUE=$(shuf -i 1-1000000 -n 1)
LOG_FOLDER="/opt/$CONTAINER_NAME/logs"
CN=$(docker ps --no-trunc -f name=$CONTAINER_NAME | awk 'print $1' | tail -n +2)
LOG_DOCKER_FILE="$(docker inspect --format='.LogPath' $CN)"
LOG_FILE_NAME="$CURRENT_DATE-$RANDOM_VALUE"

############################# Procedure:
mkdir -p "$LOG_FOLDER"
cp $LOG_DOCKER_FILE "$LOG_FOLDER/$LOG_FILE_NAME.log"
cd $LOG_FOLDER
tar -cvzf "$LOG_FILE_NAME.tar.gz" "$LOG_FILE_NAME.log"
rm -rf "$LOG_FILE_NAME.log"
truncate -s $SIZE_TO_TRUNCATE $LOG_DOCKER_FILE

您可以创建一个 cronjob 来每月运行之前的脚本。第一次运行:

sudo crontab -e

在键盘中输入 a 以进入编辑模式。然后添加以下行:

0 0 1 * * /your-script-path/script.sh

escape 键退出编辑模式。通过键入 :wq 并按 Enter 保存文件。确保 script.sh 文件具有执行权限。

【讨论】:

【参考方案9】:

也可以使用docker run 命令设置限制。

docker run -it -d -v /tmp:/tmp -p 49160:8080 --name web-stats-app --log-opt max-size=10m --log-opt max-file=5 mydocker/stats_app

【讨论】:

以上是关于Docker 容器日志占用了我所有的磁盘空间的主要内容,如果未能解决你的问题,请参考以下文章

治疗磁盘空间不足焦虑症,释放容器占用空间——Win10+docker篇

解决:关于docker闪退的问题

Docker容器日志查看与清理

解决docker容器日志导致主机磁盘空间满了的情况

Linux 迁移Docker目录/var/lib/docker

Linux 迁移Docker目录/var/lib/docker