在工作中,有一个 Docker 主机,它有一个非常小的
/var/lib/docker
,每当一些 docker build
命令连续失败时,它就会很快填满。特别是因为并非所有 docker build
命令都使用以下标志:--no-cache --force-rm --rm=true
,其要点(以我的理解)是在成功或不成功的构建后尝试删除额外的垃圾。如果您访问 Docker Docs 然后向下滚动,您可以找到这些标志。
我们遇到的一个问题是,并不是每个人都使用标志
docker build
--no-cache --force-rm --rm=true
,并且很难追踪(我知道这很愚蠢),但也可能还有其他一些原因导致填充/var/lib/docker
我们还没有抓住。 IT 不会授予我们查看该目录以更好地理解的权限,但我们可以运行 docker image prune
或 docker system prune
,这似乎是解决我们问题的一个很好的解决方案,除了我们手动运行它之外现在,每当事情变糟时。
我们正在考虑通过以下方式解决问题:a) 几乎每次构建镜像后都运行
yes | docker image prune
。我写“差不多”是因为很难追踪每个构建图像的存储库(成功与否),但这是一个单独的故事。即使这个命令有一些副作用(例如在同一台 Docker 主机上破坏其他人的同步 docker build
,它也只会偶尔运行一次,因此发生冲突的可能性很低。正在讨论的另一种方法很漂亮盲目地将 yes | docker image prune
添加到每 2 小时运行一次的 cron 作业中。如果此命令有潜在的负面影响,那么损坏的可能性就更大。
为什么我什至认为另一个
docker build
可能会损坏?好吧,我确实不知道,否则我不会问这个问题。为了更好地理解我们有时在破碎后得到的所谓图像,我阅读了这篇经常被引用的文章:https://projectatomic.io/blog/2015/07/what-are- docker-none-none-images/我的理解是,尚未完成的
docker build
最终会在磁盘上留下一些图像,然后根据标志在最后清理这些图像。然而,如果某些东西(例如并行发出的命令
docker build
)删除了一些中间图像层,那么整个构建也会失败。这是真的吗?如果是这样,那么在构建许多图像时保持yes | docker image prune
干净的好方法是什么。
/var/lib/docker
进程。在此期间还并行运行多个
docker build
进程。Dockerfile:
docker system prune
测试.sh:
FROM centos:7
RUN echo "before sleep"
RUN sleep 10
RUN echo "after sleep"
RUN touch /myfile
运行
#!/bin/bash
docker build -t test1 --no-cache . &
docker build -t test2 --no-cache . &
docker build -t test3 --no-cache . &
docker build -t test4 --no-cache . &
sleep 5
echo Prune!
docker system prune -f &
docker system prune -f &
sleep 15
docker run --rm test1 ls -la /myfile
docker run --rm test2 ls -la /myfile
docker run --rm test3 ls -la /myfile
docker run --rm test4 ls -la /myfile
我获得了成功的构建和修剪。第二次剪枝过程有一个例外:
bash test.sh
,这意味着剪枝识别出这种冲突情况。在 docker 版本 19.03.12、主机系统 centos 7 上测试
Error response from daemon: a prune operation is already running
(没有
docker image prune
选项)将仅删除悬空图像,而不删除未使用的图像。如“什么是悬挂图像以及什么是未使用图像?悬空图像是没有标签且没有子图像的图像(例如使用不同版本的-a
的旧图像),指向它们。
他们之前可能有一个指向他们的标签,但该标签后来发生了变化。 或者它们可能从未有过标签(例如,docker 构建的输出不包含标签选项)。由
生成的中间图像不应被视为悬空,因为它们有一个指向它们的子图像。因此(待测试),在构建图像时使用
docker build
应该是安全的。
此外,Buildkit现在是 Linux 上的默认版本 (moby v23.0.0),旨在避免其余 API(中间图像和容器)产生副作用:
BuildKit 的核心是低级构建 (LLB) 定义格式。 LLB 是一种中间二进制格式,允许开发人员扩展 BuildKit。 > LLB 定义了一个内容可寻址的依赖图,可用于组合非常复杂的构建定义。