对 Jenkins 管道和/或 Docker 升级中使用的 docker 构建脚本进行一些更改后,我开始遇到严重的图像数据泄漏。它们表现在图像目录
/var/lib/docker/overlay2
的大小不稳定且不断增长,该目录始终大于Docker CLI可访问和干净删除的Images
(如docker system df
所示)。在繁忙的构建服务器上,这意味着每天约有 1 TB 的图像数据泄漏,这些数据无法使用干净的 Docker CLI 方法(例如 docker system prune
)进行修剪,必须手动删除(整个 /var/lib/docker
)。
如何以可扩展的方式调试和查找此类数据泄漏的原因,这将适用于一般情况,而不仅仅是在这种情况下[1]?
我正在谈论诸如此类的情况(紧接在
docker system prune -af
之后):
$ sudo du -sch /var/lib/docker/overlay2; echo ""; docker system df
68G /var/lib/docker/overlay2
68G total
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
几乎所有这些无法访问的泄漏剩余内容都位于“diff”子文件夹中,但这不足以将它们与也存储在此类子文件夹中的有用层区分开来:
$ find | grep diff | wc -l
989599
# vs.
$ find | grep -v diff | wc -l
792
这些泄露的文件夹的内容看起来也很不可疑(所有文件扩展名,都是从源代码编译并作为预编译库提供的):
./268713830f68824c1f6f5b21aad89055c18e8c0e6f1751654ec82ca4caf5bba9/diff/opt/conda/lib/python3.11/site-packages/sklearn/ensemble/_weight_boosting.py
./268713830f68824c1f6f5b21aad89055c18e8c0e6f1751654ec82ca4caf5bba9/diff/opt/conda/lib/python3.11/site-packages/sklearn/ensemble/_gradient_boosting.cpython-311-x86_64-linux-gnu.so
./268713830f68824c1f6f5b21aad89055c18e8c0e6f1751654ec82ca4caf5bba9/diff/opt/conda/lib/python3.11/site-packages/sklearn/ensemble/tests/test_gradient_boosting.py
./268713830f68824c1f6f5b21aad89055c18e8c0e6f1751654ec82ca4caf5bba9/diff/opt/conda/lib/python3.11/site-packages/sklearn/ensemble/tests/__pycache__/test_gradient_boosting.cpython-311.pyc
./268713830f68824c1f6f5b21aad89055c18e8c0e6f1751654ec82ca4caf5bba9/diff/opt/conda/lib/python3.11/site-packages/sklearn/ensemble/tests/__pycache__/test_weight_boosting.cpython-311.pyc
./268713830f68824c1f6f5b21aad89055c18e8c0e6f1751654ec82ca4caf5bba9/diff/opt/conda/lib/python3.11/site-packages/sklearn/ensemble/tests/test_weight_boosting.py
./268713830f68824c1f6f5b21aad89055c18e8c0e6f1751654ec82ca4caf5bba9/diff/opt/conda/lib/python3.11/site-packages/scipy/special/tests/data/boost.npz
./268713830f68824c1f6f5b21aad89055c18e8c0e6f1751654ec82ca4caf5bba9/diff/opt/conda/lib/python3.11/site-packages/scipy/special/tests/test_boost_ufuncs.py
我还从
docker build
升级到 docker buildx
(Moby BuildKit 构建器工具包),至少在对一个大型容器进行几个小时的测试构建之后,情况 看起来 更有希望,因为 /var/lib/docker/overlay2
很稳定并且从未增长大于图像所需的大小,如 docker system df
所示。但是,由于容器被删除(并且 docker 系统被修剪)后存储无法回收,因此随着时间的推移,构建仍然会占用所有可用空间,这只是时间问题,而不是是否问题:
$ sudo du -sch /var/lib/docker/overlay2; echo ; docker system df build-srv-3-fi: Sun Jul 28 14:43:42 2024
117G /var/lib/docker/overlay2
117G total
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 buildx version v0.15.1 1c1dbb2
下)
此问题似乎不受用于清理数据的方法的影响(例如,删除第一个图像然后构建缓存并不比使用全部方法更好
docker system prune
)。
[1] 即不限于我相当复杂的设置,在 Docker Compose 中运行的 dockerized Jenkins 构建(并行)数十个具有部分重叠图像层和/或互连(多级)容器的管道,需要 4 个额外的服务容器(例如Jenkins)来构建每个“业务”容器。
问题似乎取决于清理方法。如果您尝试采用两阶段方法,分别清理图像和构建缓存,那么在第二个清理阶段之后,
/var/lib/docker/overlay2
文件夹将从清空的构建缓存中接收所有文件/文件夹,并且需要手动干预(删除)。但是,如果您一次性停止所有正在运行的容器并修剪 docker 系统,那么这些文件将永远消失。
方法一(无效):
$ docker rmi -f $(docker images -aq)
$ docker builder prune -af
overlay2
文件夹,但从上一级完成其所有父目录:$ rm -rf /var/lib/docker
方法2(有效):
$ docker system prune -af