相关文章: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-driver
和log-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的默认日志驱动。syslog
、journald
、fluentd
、gelf
、awslogs
、splunk
等,便于将日志直接发送到远程服务或日志聚合系统中。
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优点
- 控制日志文件大小:防止单个日志文件过大,影响系统性能或占用过多磁盘空间。
- 日志文件数量限制:通过限制日志文件数量,可以有效管理磁盘空间。
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.1
到container_id-json.log.7
)。在创建新的日志轮转文件时,最老的一个日志文件会被删除。
- 指定保留的日志文件数量。在这个配置中,最多会保留 7 个轮转后的日志文件,如,
daily
:- 指定日志轮转的频率为每天一次。每次运行
logrotate
时,如果日志文件已经存在并且符合轮转条件(如大小或时间),日志将被轮转。
- 指定日志轮转的频率为每天一次。每次运行
compress
:- 指定轮转后的日志文件将被压缩,通常是使用
gzip
压缩为.gz
文件,有助于节省磁盘空间。
- 指定轮转后的日志文件将被压缩,通常是使用
size=100M
:- 指定日志文件达到 100MB 时触发轮转。即使设置了
daily
,如果日志文件在一天内未达到 100MB,也不会被轮转;但如果日志文件在一天内达到了 100MB,将立即轮转日志文件。
- 指定日志文件达到 100MB 时触发轮转。即使设置了
missingok
:- 指定如果日志文件不存在,则不会报错并继续进行。避免了由于某些日志文件缺失而导致的错误。
delaycompress
:- 指定延迟压缩轮转后的日志文件。也就是说,日志文件不会在第一次轮转时立即压缩,而是在下次轮转时才压缩。这个设置可以保证如果在轮转后日志文件仍然在被写入时,不会立即压缩影响性能。
copytruncate
:- 用于处理那些无法轻易关闭并重新打开日志文件的应用程序。
copytruncate
会复制现有的日志文件并截断原始文件,而不是移动或删除原始文件。这样,应用程序可以继续向原始文件写入日志而不会中断。这适用于一些不能通过信号触发日志轮转的应用程序。
- 用于处理那些无法轻易关闭并重新打开日志文件的应用程序。
3.手动执行Logrotate
logrotate -f /etc/logrotate.d/docker-containers #使用 -f 强制执行轮转一次
4. logrotate
工作流程
结合这些选项,这个 logrotate
配置的工作流程如下:
- 每天检查一次日志文件。
- 如果日志文件的大小达到了 100MB 或更多,它将被轮转。
- 最多保留 7 个轮转后的日志文件。
- 在轮转时,日志文件不会立即被压缩,而是在下一个轮转周期才压缩。
- 如果日志文件缺失,不会报错。
- 使用
copytruncate
,在轮转后原始日志文件将被截断,以便应用程序可以继续向同一个日志文件写入。
五. Logrotate
和Docker Log-driver
适用场景对比
Logrotate
更适合管理传统应用程序的日志,尤其是在需要复杂的日志轮转策略和定制化管理时。它在系统级别上运行,适用于管理所有类型的日志文件。Docker Log-driver
更适合管理容器化应用的日志,尤其是当你希望直接将日志输出到日志聚合服务或远程存储时。它集成性更强,更适合现代云原生架构。
总结
配置和管理日志的选择取决于你的具体需求和环境。如果需要灵活性和复杂的日志策略,Logrotate是更好的选择;如果管理容器化应用并需要简化日志管理,Docker的log-driver可能更合适。