如何清理Docker容器占用磁盘空间并配置日志轮转

相关文章:promtail + loki + grafana 日志看板平台,帮助开发快速通过日志定位问题

Docker容器占用磁盘的原因及解决方法

一、原因分析

1. 镜像与容器残留

  • 未删除的旧镜像、停止的容器、未清理的网络和卷。

2.日志文件增长

  • Docker默认不对日志文件进行轮转,导致日志文件无限增长,占用大量磁盘空间。

3.容器内临时目录占用

  • 容器内的临时目录及隐藏文件可能占用大量磁盘空间,不易发现

二、清理Docker占用的磁盘空间

如果容器中有大量未使用的数据卷、旧镜像和构建缓存,可以使用以下Docker命令来清理:

1. 清理未使用的数据卷docker volume prune

2.清理未使用的镜像docker image prune -a

3.清理未使用的容器docker container prune

4.清理未使用的网络docker network prune

清理之后,发现磁盘还是满的,没什么效果,接下来使用脚本来查看哪个容器占用的磁盘比较大,来针对性的清理

5.使用shell脚本清理容器日志或临时目录

  • 查看容器磁盘使用情况
#!/bin/bash

# 列出所有容器ID和名称
containers=$(docker ps -a --format "{{.ID}} {{.Names}}")

# 遍历所有容器,计算磁盘使用情况
echo "容器ID 容器名称 磁盘使用情况"
while IFS= read -r container; do
    id=$(echo $container | awk '{print $1}')
    name=$(echo $container | awk '{print $2}')
    dir=$(docker inspect -f '{{.GraphDriver.Data.MergedDir}}' $id)
    size=$(du -sh $dir | awk '{print $1}')
    echo "$id $name $size"
done <<< "$containers"

有个容器,tmp临时目录占用 79G,日志文件占用 17G

  • 清理日志和临时目录
#!/bin/bash
for container in $(docker ps --no-trunc|awk 'NR==2{print $1}'); do
  truncate -s 0 /var/lib/docker/containers/$container/$container-json.log
  #清理临时目录
  docker exec -it $container sh -c 'rm -rf /tmp/*'
done

docker ps –no-trunc|awk ‘NR==2{print $1}’用来获取容器的完整 ID

清理之后,磁盘使用率从100%降到了 16%,此时在启动 docker容器业务就正常了,博主docker中临时跑了一个爬虫的业务,不重要,就这样给清掉也无所谓

docker容器跑的业务比较重要的话,日志就不能直接暴力的清理掉,还是要做日志轮转、聚合等,方便查询定位问题,为了不再出现这种写满磁盘的问题,接下来做 docker容器的日志轮转

三、配置Docker日志轮转

在Docker中,日志驱动和日志选项的配置可以帮助管理和限制容器日志的大小,以防止日志文件占用过多的磁盘空间。

1. 编辑全局配置文件/etc/docker/daemon.json

新增log-driverlog-opts相关配置

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  }
}

以下是"log-driver": "json-file""log-opts"的详细解释:

"log-driver": "json-file" log-driver选项指定了Docker使用的日志驱动。"json-file"表示Docker将日志存储为JSON文件。这是Docker的默认日志驱动。syslogjournaldfluentdgelfawslogssplunk 等,便于将日志直接发送到远程服务或日志聚合系统中。

log-opts选项用于配置与日志驱动相关的参数,有两个参数:

  • max-size“: “100m”
    • 这个参数指定了单个日志文件的最大大小。
    • “100m”表示每个日志文件的最大大小为100兆字节(MB)。
    • 当日志文件的大小超过100MB时,Docker会轮转日志文件。
  • max-file“: “3”
    • 这个参数指定了保留的最大日志文件数量。
    • 3表示最多保留3个日志文件,包括当前日志文件和两个轮转的日志文件。
    • 当达到这个数量时,最旧的日志文件将被删除,以腾出空间存储新的日志文件。

更多日志配置可看docker官方文档

2. 重新加载配置并重启Docker服务

配置完成后,重新加载配置,在启动Docker服务以使更改生效:

systemctl daemon-reload
systemctl restart docker

每次修改配置一定要daemon-reload下,不然重启报错

3. 验证配置是否生效

#查看配置是否生效
docker inspect --format='{{.HostConfig.LogConfig}}' <container_id> 
{json-file map[]} #返回结果显示没生效
#销毁容器
docker-compose down
#重新创建容器
docker-compose up -d 
#再次查看配置是否生效
docker inspect --format='{{.HostConfig.LogConfig}}' <container_id>
{json-file map[max-file:3 max-size:100m]}
#此时配置生效了

备注:docker-compose中做了数据持久化,删除容器并不会丢失数据哦

4. 配置单个容器的日志选项

如果不想修改全局配置/etc/docker/daemon.json重新创建容器(使用新的日志配置):

docker stop <container_id>
docker rm <container_id>
#重新创建容器
docker run -d --log-driver=json-file --log-opt max-size=100m --log-opt max-file=3 my_container

5. Docker Log-driver工作原理

  • 日志文件轮转:当日志文件的大小达到10MB时,Docker会创建一个新的日志文件,并将旧的日志文件重命名。例如,container_id-json.log变为container_id-json.log.1,新的日志文件开始记录。
  • 日志文件数量限制:最多保留3个日志文件(当前日志文件和两个轮转的日志文件)。当创建新的日志文件时,如果已有3个日志文件,最旧的一个将被删除。

6. Docker Log-driver优点

  1. 控制日志文件大小:防止单个日志文件过大,影响系统性能或占用过多磁盘空间。
  2. 日志文件数量限制:通过限制日志文件数量,可以有效管理磁盘空间。

7. Docker Log-driver缺点

修改全局配置需要重启 docker,这意味着, docker中的容器不能对外提供服务,影响业务

已有的docker容器不会生效Log-driver配置,需要重新创建容器

所以最好是在安装 docker后,配置Log-driver, 重启docker后,创建容器不用指定log-driver相关配置,后面无论是 docker run 还是 docker-compose创建容器,都不用指定log-driver相关配置,方便了很多,更能保证容器的稳定性

如果 docker容器正对外提供服务,使用Logrotate来切割日志,最为合适。

四、使用Logrotate管理日志

可以使用logrotate工具来管理和轮转日志文件,防止日志文件占用过多磁盘空间。使用起来更加灵活,参数多

1. 安装Logrotate

  • 在CentOS上安装Logrotate
yum install logrotate -y
  • Ubuntu/Debian上安装Logrotate
apt-get install logrotate -y

2. 配置logrotate

创建或编辑 /etc/logrotate.d/docker-containers 文件:

/var/lib/docker/containers/*/*.log {
    rotate 7
    daily
    compress
    size=100M
    missingok
    delaycompress
    copytruncate
}
  • rotate 7:
    • 指定保留的日志文件数量。在这个配置中,最多会保留 7 个轮转后的日志文件,如,container_id-json.log.1container_id-json.log.7)。在创建新的日志轮转文件时,最老的一个日志文件会被删除。
  • daily:
    • 指定日志轮转的频率为每天一次。每次运行 logrotate 时,如果日志文件已经存在并且符合轮转条件(如大小或时间),日志将被轮转。
  • compress:
    • 指定轮转后的日志文件将被压缩,通常是使用 gzip 压缩为 .gz 文件,有助于节省磁盘空间。
  • size=100M:
    • 指定日志文件达到 100MB 时触发轮转。即使设置了 daily,如果日志文件在一天内未达到 100MB,也不会被轮转;但如果日志文件在一天内达到了 100MB,将立即轮转日志文件。
  • missingok:
    • 指定如果日志文件不存在,则不会报错并继续进行。避免了由于某些日志文件缺失而导致的错误。
  • delaycompress:
    • 指定延迟压缩轮转后的日志文件。也就是说,日志文件不会在第一次轮转时立即压缩,而是在下次轮转时才压缩。这个设置可以保证如果在轮转后日志文件仍然在被写入时,不会立即压缩影响性能。
  • copytruncate:
    • 用于处理那些无法轻易关闭并重新打开日志文件的应用程序。copytruncate 会复制现有的日志文件并截断原始文件,而不是移动或删除原始文件。这样,应用程序可以继续向原始文件写入日志而不会中断。这适用于一些不能通过信号触发日志轮转的应用程序。

3.手动执行Logrotate

logrotate -f /etc/logrotate.d/docker-containers #使用 -f 强制执行轮转一次

4. logrotate工作流程

结合这些选项,这个 logrotate 配置的工作流程如下:

  • 每天检查一次日志文件。
  • 如果日志文件的大小达到了 100MB 或更多,它将被轮转。
  • 最多保留 7 个轮转后的日志文件。
  • 在轮转时,日志文件不会立即被压缩,而是在下一个轮转周期才压缩。
  • 如果日志文件缺失,不会报错。
  • 使用 copytruncate,在轮转后原始日志文件将被截断,以便应用程序可以继续向同一个日志文件写入。

五. LogrotateDocker Log-driver 适用场景对比

  • Logrotate 更适合管理传统应用程序的日志,尤其是在需要复杂的日志轮转策略和定制化管理时。它在系统级别上运行,适用于管理所有类型的日志文件。
  • Docker Log-driver 更适合管理容器化应用的日志,尤其是当你希望直接将日志输出到日志聚合服务或远程存储时。它集成性更强,更适合现代云原生架构。

总结

配置和管理日志的选择取决于你的具体需求和环境。如果需要灵活性和复杂的日志策略,Logrotate是更好的选择;如果管理容器化应用并需要简化日志管理,Docker的log-driver可能更合适。

Comments

No comments yet. Why don’t you start the discussion?

发表评论