清理 Docker 占用磁盘空间

清理 Docker 占用磁盘空间_第1张图片

前言

Docker 容器跑久了,其产生的日志可能会占用比较多的空间,如果你跟我一样,使用的小水管级的服务器,很容易就爆了,此时就需要清理一下,今天恰巧遇到这种情况,具体如下图:

清理 Docker 占用磁盘空间_第2张图片

从上图可知,空间使用率已经 100% 了,这些数据主要集中在 docker 的 overlay2 上,借此清理 Docker 的机会,回顾一下 Docker 相关的一些知识。

查看 Docker 空间占用

有了 Docker,多数情况下,我们可以不再需要过于关心环境问题,但也付出了一些代价,占用空间便是其中一点。

通过下面命令,可以知道 Docker 占用空间的情况:

docker system df

该命令列出了 docker 使用磁盘的 4 种类型:

  • Images: 所有镜像占用的空间,包括拉取的镜像、本地构建的镜像

  • Containers: 运行中的容器所占用的空间(没运行就不占空间),其实就是每个容器读写层的空间

  • Local Volumes: 本地数据卷的空间

  • Build Cache: 镜像构建过程中,产生的缓存数据

对我而言,这个命令我还会加上 - v 参数,即 docker system df -v,效果如下图:

清理 Docker 占用磁盘空间_第3张图片

这图我主要看的信息就是哪些容器、数据卷是没有被使用的,此时可以通过下面命令清理 Docker 占用的空间。

docker system prune -a

该命令会删除暂停中的容器、没有关联容器的镜像、没有 tag 的镜像、没有被使用的数据卷,简单而言,没有在 run 或被使用的东西都被清理掉,注意,如果你有一些暂时暂停的容器,这个命令也会将其清理掉。

为了深入理解上述命令的作用,先讨论一下在使用 docker 镜像创建容器时,docker会创建哪些目录:

我们使用 docker 镜像创建容器时,docker会创建一些目录,如:

  • /var/lib/docker/containers/<容器ID> 目录,如果容器使用了默认的日志模式,那么该容器的日志会以 JSON 形式保存在此目录下。

  • /var/lib/docker/overlay2 目录,该目录包含容器的读写层,如果容器使用自己的文件系统保存了数据,那么这些数据就会写到此目录下。

为了更直观,弄一台干净的 Linux 服务器(刚好去年双 11 买了 Linux 服务器),演示创建容器过程中,docker 占用空间的变化。

一开始,docker 没有占用任何空间:

[root@clickhouse ~]# docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          0         0         0B        0B
Containers      0         0         0B        0B
Local Volumes   0         0         0B        0B
Build Cache     0         0         0B        0B

拉取 busybox镜像,看占用磁盘空间

BusyBox 是一个集成了一百多个最常用 Linux 命令和工具(如 cat、echo、grep、mount、telnet 等)的精简工具箱,它只需要几 MB 的大小,很方便进行各种快速验证,被誉为 “Linux 系统的瑞士军刀”。

可以发现 Images 行,有了 busybox 镜像占用的空间

[root@clickhouse ~]# docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          1         1         1.24MB    0B (0%)
Containers      1         1         0B        0B
Local Volumes   0         0         0B        0B
Build Cache     0         0         0B        0B

然后我们运行 busybox 并创建 100M 的空文件,命令为:

[root@clickhouse ~]# docker run -it busybox
# 创建名为ayu.img的空文件
/ # dd if=/dev/zero of=ayu.img bs=1024 count=102400
102400+0 records in
102400+0 records out
104857600 bytes (100.0MB) copied, 0.403244 seconds, 248.0MB/s
/ #

占用空间如下图所示:

[root@clickhouse ~]# docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          1         1         1.24MB    0B (0%)
Containers      1         1         104.9MB   0B (0%)
Local Volumes   0         0         0B        0B
Build Cache     0         0         0B        0B

可以发现,Containers 行的 SIZE 变为了 104.9MB,此时这些被占用空间是不可被回收的(RECLAIMABLE 列还是为 0B)。

如果你没有修改 docker 默认的配置,此时空文件会保存在 /var/lib/docker 目录中的某个位置,可以通过 find 命令准确定位出来,命令如下:

#查找名为ayu.img的空文件
[root@clickhouse ~]# find /var/lib/docker/ -type f -name ayu.img
/var/lib/docker/overlay2/f0c37adb84cfe3ccefcb25434f374235a8d99c157be6f8eb1c8389de18c2152b/merged/ayu.img
/var/lib/docker/overlay2/f0c37adb84cfe3ccefcb25434f374235a8d99c157be6f8eb1c8389de18c2152b/diff/ayu.img

当我们停止 busybox 容器后,容器占用的空间就变得可回收了,效果如下:

[root@clickhouse ~]# docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          1         1         1.24MB    0B (0%)
Containers      1         0         104.9MB   104.9MB (100%)
Local Volumes   0         0         0B        0B
Build Cache     0         0         0B        0B

看到 Containers 行的 RECLAIMABLE 列,其值变为 104.9MB,即此时容器停止了,容器占用的空间可以被回收了。

然后便可以通过 docker system prune -a 删除所有不使用的镜像、容器和数据卷了,效果如下:

[root@clickhouse ~]# docker system prune -a
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all images without at least one container associated to them
  - all build cache

Are you sure you want to continue? [y/N] y
Deleted Containers:
c4f21e236ad67513e2d5dbe92ebaae71f5609217575b6e996d95a96ad0237450

Deleted Images:
untagged: busybox:latest
untagged: busybox@sha256:afcc7f1ac1b49db317a7196c902e61c6c3c4607d63599ee1a82d702d249a0ccb
deleted: sha256:ec3f0931a6e6b6855d76b2d7b0be30e81860baccd891b2e243280bf1cd8ad710
deleted: sha256:d31505fd5050f6b96ca3268d1db58fc91ae561ddf14eaabc41d63ea2ef8c1c6d

Total reclaimed space: 106.1MB
[root@clickhouse ~]# docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          0         0         0B        0B
Containers      0         0         0B        0B
Local Volumes   0         0         0B        0B
Build Cache     0         0         0B        0B

如果不希望删除镜像,而只是将无用的数据卷、容器等删除,则使用 docker system prune 命令(即不添加 - a 参数),效果如下:

[root@clickhouse ~]# docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          1         1         1.24MB    0B (0%)
Containers      1         0         104.9MB   104.9MB (100%)
Local Volumes   0         0         0B        0B
Build Cache     0         0         0B        0B
[root@clickhouse ~]# docker system prune   
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
Deleted Containers:
f751982675af0e510fde360b08e4734c8c2d0d43260b2065610e66932db44186

Total reclaimed space: 104.9MB
[root@clickhouse ~]# docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          1         0         1.24MB    1.24MB (100%)
Containers      0         0         0B        0B
Local Volumes   0         0         0B        0B
Build Cache     0         0         0B        0B

df 与 du 不匹配

因为我不在乎 docker 镜像数据,根据上面的讨论,通过 docker system prune -a 命令清除一下就好了,如下图所示,清理了 897.1MB

清理 Docker 占用磁盘空间_第4张图片

清理后,发现空间占用小了一点,但无济于事,如下图:

清理 Docker 占用磁盘空间_第5张图片

通过上面的操作,Docker 相关的数据应该清理干净了,但是磁盘空间却没有明显的降低,而且通过 df 命令查看,overlay2 依旧占据大量空间,这是怎么回事?

很明显,出现了意料之外的情况,简单思索,我并不在乎当前 docker 容器中的数据,既然 docker system prune -a 没啥效果,那么就上 df 命令与 du 命令,定位出占据磁盘空间最大的文件或文件夹,直接删除它就好了。

很快我发现 df 命令查询出的磁盘空间占用大小与 du 命令查询出的磁盘空间占用大小不同,如下图所示:

清理 Docker 占用磁盘空间_第6张图片

之所以出现这种情况,通常是因为很多删除的文件依旧被某些程序引用着,导致磁盘空间无法被回收,对于这种情况,df 命令会统计,即认为空间还是被占用着,而 du 命令不会统计,从而导致了两个命令统计出的磁盘空间其大小是不同的。

通过 lsof | grep deleted 命令查看那些引用着被删除文件的进程,发现了一堆,如下图:

清理 Docker 占用磁盘空间_第7张图片

将这些进程 kill 掉,再看 df 和 du 就一致了。

清理 Docker 占用磁盘空间_第8张图片

此时,Docker 占用的磁盘空间就被清理出来了。

docker 构建失败

因为在清理过程中,我尝试过强制删除了 overlay2 下的文件,这导致使用 docker 构建镜像时,会报 failed to create rwlayer: symlink 错误:

failed to create rwlayer: symlink ../d09af977422891715fe2ec64c353b761481337720a906228f3cdc335df1850b3/diff /volumes01/docker/overlay2/l/POZR4HXDGJ32OEJJZHXJKQMTOS: no such file or directory

此时重新启动一下 docker 便可解决这个问题

dae2d46e84503ea7ede532d4b156c657.png

结尾

这篇文章写在周日时光,我特意去公司加班,打算研究点项目,结果被这事消耗了些时间,果然,运维类问题永远是时间杀手。

我是二两,记录就水到这,我们下篇文章见。

你可能感兴趣的:(运维,docker,java,linux,python)