为什么文件会不断增大?
如果经常使用 Docker,即使删除文件,Docker.raw
(或Docker.qcow2
)的大小也可能会不断增大。
为了展示这种影响,请先在主机上检查文件的当前大小:
$ cd ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/
$ ls -s Docker.raw
9964528 Docker.raw
请注意使用了
-s
参数,它显示了文件实际使用的文件系统块数。实际使用的块数不一定与文件的“大小”相同,因为文件可以是
稀疏的。
接下来在单独的终端中启动一个容器并创建一个1GiB的文件:
$ docker run -it alpine sh
/
1024+0 records in
1024+0 records out
/
回到主机后,再次检查文件大小:
$ ls -s Docker.raw
12061704 Docker.raw
请注意,从
9964528
增加到
12061704
,增加的
2097176
个
512
字节扇区约为 1GiB,正如预期的那样。如果您切换回
alpine
容器终端并删除该文件:
/ # rm -f 1GiB
/ # sync
然后在主机上检查文件:
$ ls -s Docker.raw
12059672 Docker.raw
文件大小并没有变小!无论虚拟机中的文件发生了什么,主机似乎并不知道。
接下来,如果您再次在容器中创建“相同”的1GiB
文件,然后再次检查文件大小,您会看到:
$ ls -s Docker.raw
14109456 Docker.raw
它甚至变得更大了!如果你在一个循环中创建和销毁文件,即使虚拟机内部的文件系统相对空闲,Docker.raw
(或Docker.qcow2
)的大小也会增加到上限(目前设置为64 GiB)。
这种奇怪行为的解释在于文件系统通常如何管理块。当需要创建或扩展文件时,文件系统会找到一个空闲块并将其添加到文件中。当删除文件时,从文件系统的角度来看,这些块变为“空闲”,但没有人告诉磁盘设备。更糟糕的是,新释放的块可能不会立即被重新使用,完全取决于文件系统的块分配算法。例如,该算法可能设计为优先为文件分配连续的块:最近释放的块可能不是用于扩展文件的理想位置。
由于实际上块分配器倾向于未使用的块,因此结果是Docker.raw
(或Docker.qcow2
)将不断积累新的块,其中许多包含过期数据。尽管虚拟机内部的文件系统仍报告有足够的可用空间,但主机上的文件会变得越来越大。
TRIM
TRIM命令(或DISCARD
或UNMAP
)允许文件系统向磁盘发出信号,表明一些扇区包含过期数据,可以被遗忘。这允许:
- 使用SSD固态硬盘擦除并重复利用空间,而不是花费时间来移动它;
- 使用Docker for Mac释放主机文件系统中的块,缩小文件。
那么我们该如何实现呢?
Docker for Mac中的自动TRIM
在Docker for Mac 17.11中,有一个名为trim-after-delete
的containerd“任务”监听Docker镜像删除事件。可以通过ctr
命令查看:
$ docker run --rm -it --privileged --pid=host walkerlee/nsenter -t 1 -m -u -i -n ctr t ls
TASK PID STATUS
vsudd 1741 RUNNING
acpid 871 RUNNING
diagnose 913 RUNNING
docker-ce 958 RUNNING
host-timesync-daemon 1046 RUNNING
ntpd 1109 RUNNING
trim-after-delete 1339 RUNNING
vpnkit-forwarder 1550 RUNNING
当接收到图像删除事件时,该过程会等待几秒钟(以防其他图像正在被删除,例如作为
docker system prune 的一部分),然后在文件系统上运行
fstrim
。
回到前面一节的示例,如果您删除了
alpine
容器内的 1 GiB 文件。
/ # rm -f 1GiB
然后在主机的终端中手动运行fstrim
:
$ docker run --rm -it --privileged --pid=host walkerlee/nsenter -t 1 -m -u -i -n fstrim /var/lib/docker
然后检查文件大小:
$ ls -s Docker.raw
9965016 Docker.raw
文件已经回到(大约)原始大小——空间终于被释放了!
希望
这篇博客有所帮助,此外,请查看以下macOS Docker实用脚本以解决此问题:
https://github.com/wanliqun/macos_docker_toolkit
duc
报告的是表面大小而不是实际大小,所以我需要避免对此过于担忧。对于任何其他使用它的人,在 GUI 显示时按下a
键可以在表面大小和实际大小之间切换。 - Sridhar Sarnobat