Mdaeo'Blog

清理Docker占用的磁盘空间

当你使用 docker,并且容器运行比较久,程序又疯狂的输入后,就会导致 docker的日志占用磁盘空间太大,这时候就需要清理一下了。

根据以住的解决问题的思路,这次记录下来,方便以后查阅,也给其遇到此问题的小伙伴一个参考。

查看磁盘空间

$ df -hl

输出

Filesystem      Size  Used Avail Use% Mounted on
tmpfs           794M  5.3M  789M   1% /run
/dev/vda1       148G   73G   69G  52% /
tmpfs           3.9G     0  3.9G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           794M     0  794M   0% /run/user/0
overlay         148G   73G   69G  52% /var/lib/docker/overlay2/cb00c5676cee609000b56c66a73799105a373aad0700c5568f3d361a38089b78/merged
overlay         148G   73G   69G  52% /var/lib/docker/overlay2/64abd807c2a1b351718b5a3ddacd81ff65cb8a93b350a8ca7739a297b9800edb/merged
overlay         148G   73G   69G  52% /var/lib/docker/overlay2/f1100b6702df33a0fa0557b73ed56952cfa0385c182fd271c142b9d6204fdecd/merged
overlay         148G   73G   69G  52% /var/lib/docker/overlay2/44f6aa5c75d6e4f31747398e89bc369b63b9aad27623e8766636bbea58ae32d8/merged
........

看输出docker目录占用太多磁盘空间了,那就可以找对应的解决方案了。

docker system 命令

docker system df命令,类似于 Linux 上的df命令,用于查看 Docker 的磁盘使用情况:

docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          56        55        4.011GB   78.94MB (1%)
Containers      60        60        212.3MB   0B (0%)
Local Volumes   5         2         1.378kB   92B (6%)
Build Cache     0         0         0B        0B

可以看,Docker 镜像、容器、数据卷占用了多少磁盘空间。

docker system prune命令可以用于清理磁盘,删除关闭的容器、无用的数据卷和网络,以及 dangling 镜像(即无 tag 的镜像)。

docker system prune

之前已经执行过了,所以看到是 0B

WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all dangling images
  - all dangling build cache

Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B

docker system prune -af命令清理得更加彻底,可以将没有容器使用 Docker 镜像都删掉。

docker system prune -af

可以放到释放空间 69.58MB,如果有很空未使用的镜像,容器和数据卷,释放的空间还是很可观的。

Deleted Images:
untagged: google/cadvisor:latest
untagged: google/cadvisor@sha256:815386ebbe9a3490f38785ab11bda34ec8dacf4634af77b8912832d4f85dca04
deleted: sha256:eb12107075737019dce2d795dd82f5a72197eb3c64b2140392eaad3ba3b8a34e
deleted: sha256:3385ca422448a4891ab08f24daec3f368197be67f5c786779651f1e85cffa89b
deleted: sha256:f62b8bf389e3af31123f6529d42fb6ef233e0677284af9f4d1db8513d46d6bc8
deleted: sha256:cd7100a72410606589a54b932cabd804a17f9ae5b42a1882bd56d263e02b6215

Total reclaimed space: 69.58MB

上边是自动清理,那就可以手动清理,网上一抓一大把,我这里就不做介绍了,我这里介绍一种比较简单的方法。

如 删除所有 tag 的镜像

docker rmi $(docker images | grep "^<none>" | awk "{print $3}")

/var/lib/docker/overlay2 磁盘爆满

接下我们继续查看 df -hl磁盘空间

Filesystem      Size  Used Avail Use% Mounted on
......

overlay         148G   73G   68G  52% /var/lib/docker/overlay2/cb00c5676cee609000b56c66a73799105a373aad0700c5568f3d361a38089b78/merged
overlay         148G   73G   68G  52% /var/lib/docker/overlay2/64abd807c2a1b351718b5a3ddacd81ff65cb8a93b350a8ca7739a297b9800edb/merged
overlay         148G   73G   68G  52% /var/lib/docker/overlay2/f1100b6702df33a0fa0557b73ed56952cfa0385c182fd271c142b9d6204fdecd/merged
overlay         148G   73G   68G  52% /var/lib/docker/overlay2/44f6aa5c75d6e4f31747398e89bc369b63b9aad27623e8766636bbea58ae32d8/merged
overlay         148G   73G   68G  52% /var/lib/docker/overlay2/2561c9ef9513026d3465f7e07364ce7f34a472f307c097685e28c522c1118b3f/merged

.......

依然还是 /var/lib/docker/overlay2 容器输出的日志太大,导致目录占用的磁盘空间太大。

关于 overlay2的介绍,可以参考:

官方文档 Use the OverlayFS storage driver

官方文档 Use the OverlayFS storage driver

那就继续找 元凶,进行到 /var/lib/docker目录中,使用 du -h --max-depth=1命令,查看目录占用的磁盘空间

$ cd /var/lib/docker
$ du -h --max-depth=1
4.0K    ./swarm
4.0K    ./tmp
80K    ./volumes
4.0K    ./runtimes
304K    ./network
108K    ./buildkit
du: cannot access './overlay2/d41f6fcde566b05684ec84b0db63a2fd415abfe9ef3358a66fc6194eb80bc2ad': No such file or directory
du: cannot access './overlay2/d41f6fcde566b05684ec84b0db63a2fd415abfe9ef3358a66fc6194eb80bc2ad-init': No such file or directory
8.7G    ./overlay2
16K    ./plugins
35G    ./containers
20M    ./image
43G    .

发现 containers目录占用空间最大,继续查看

Containers 包含的我们容器自身的容量、产生的数据容量、产生的日志容量

$ cd containers
$ du -h --max-depth=1
......
376K    ./b84aafb5508aaa1fa5eb94d25997928ded41f6030b8f6785245cfbee40bd1c20
1.6G    ./a89cd1bcecbc43be22bdb792f779059f6b03b716a724ac35cc6a80d70b3f83cd
48K    ./b12c8ec602a84f8898b6d5b8318ce858788fe46c7040ed449e4a7051144d380b
21G    ./807edbf4dbcf6cb4239eead128439c5e5667d56fe951f341fcf0325dab2d6a30
.....

看到有一个 21G的目录 807edbf4dbcf6cb4239eead128439c5e5667d56fe951f341fcf0325dab2d6a30,这也是容器的ID。

复制容器ID的前10个字符,查看是哪个容器

docker ps | grep 807edbf4d | awk '{print $1 "  " $2}'
容器ID         镜像
807edbf4dbcf  nginx:alpine

我们先使用命令删除日志

$ truncate -s 0 /var/lib/docker/containers/807edbf4dbcf6cb4239eead128439c5e5667d56fe951f341fcf0325dab2d6a30/807edbf4dbcf6cb4239eead128439c5e5667d56fe951f341fcf0325dab2d6a30-json.log

在使用 du -h --max-depth=1命令查看磁盘空间

$ du -h --max-depth=1
......
376K    ./b84aafb5508aaa1fa5eb94d25997928ded41f6030b8f6785245cfbee40bd1c20
1.6G    ./a89cd1bcecbc43be22bdb792f779059f6b03b716a724ac35cc6a80d70b3f83cd
48K    ./b12c8ec602a84f8898b6d5b8318ce858788fe46c7040ed449e4a7051144d380b
76K    ./807edbf4dbcf6cb4239eead128439c5e5667d56fe951f341fcf0325dab2d6a30
......

哇哦,看到了吗? 变为了 76K,这就是我们要的效果。

限制日志大小

可以参与官方文档自行尝试 Configure logging drivers

批量清理

程序员都是懒惰的,我们不想一个一个的去清理,那就写个脚本,自动化起来。

准备脚本

path=/var/lib/docker/containers/
echo ""
echo "========== Clean Docker Containers Log =========="
echo "Path: "$path
cd $path
for file in $(ls)
do
    if [ -d $file ];then
        echo $file"-json.log"
        cat /dev/null > $file/$file-json.log
      else
        echo 0
    fi
done
echo "========== Clean Docker Containers Log =========="
echo ""

把这保存为 clean_docker_container_log.sh,记得设置可执行权限,然后执行

$ ./clean_docker_container_log.sh

$ du -h --max-depth=1
....
32K    ./b84aafb5508aaa1fa5eb94d25997928ded41f6030b8f6785245cfbee40bd1c20
1.6M    ./a89cd1bcecbc43be22bdb792f779059f6b03b716a724ac35cc6a80d70b3f83cd
32K    ./b12c8ec602a84f8898b6d5b8318ce858788fe46c7040ed449e4a7051144d380b
32K    ./5107888903e6f03d00ff5ea8454a6710fc07a9143dc42fa9a2996ad1c0d84d51
....

还记得之前有个 1.6G的容器吗? 现在变成了1.6M,这就是我们要的效果。

自动化

接下来我们自动化起来,配置自动化执行上边的脚本,在对应的机器上配置crontab

  1. crontab -e
  2. 添加如下指令,替换你自己的文件路径
# clean docker container log
 # 每周一3点执行
 0 3 * * 1 sh /root/clean_docker_container_log.sh

总结

总之不管是docker原因,还是其它原因,通过正确的方法,找到问题,去解决问题,才是最重要的。

希望以上会对你有所帮助,如果有不对的地方,欢迎指正。

当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »