如何设置docker在每个构建步骤中使用来自注册表的缓存

Ser*_*rCe 16 caching docker docker-registry

我有两台带有docker的服务器和一台带有私有注册表的服务器.

我在第一台机器上建了Dockerfile; 然后我将图像推送到注册表.

是否可以使用我的注册表中的缓存立即在第二台机器上构建Dockerfile?如果不是,有没有办法加速构建"几乎"相同的Dockerfiles而不编写我自己的缓存?

它试图设置,--registry-mirror但它没有帮助.

Von*_*onC 26

注意:问题20316("拉动构建缓存")已关闭,因为PR 26839("基于历史数组实现构建缓存")已合并.

例如,它允许在--cache-from先前CI构建的图像中指定.

添加指定在构建时用作缓存源的图像的功能.这些图像不需要具有本地父链,可以从其他注册表中提取.用户需要确保仅使用受信任的图像作为源.

用法:

docker pull myimage:v1.0
docker build --cache-from myimage:v1.0 -t myimage:v1.1 .
Run Code Online (Sandbox Code Playgroud)

有关docker 1.13(2017年1月),请参阅合并提交7944480.

评论如下javipolo:

如果有人像我一样疯狂地重复使用图层,那么"技巧"就是传递给--cache-from你正在重建的图像(并且已经将其拉出)以及它用作图像的基础FROM.

示例:
Dockerfile用于图像custom-gource:0.1

FROM base_image:2.2.1
RUN apt-get update && apt-get install gource
COPY myscript.sh /myscript.sh
Run Code Online (Sandbox Code Playgroud)

为了在不重复的情况下在其他主机中重建apt-get,您需要:

docker pull custom-gource:0.1
docker build --cache-from=base_image:2.2.1,custom-gource:0.1 . -t custom-gource:0.2
Run Code Online (Sandbox Code Playgroud)

这看起来似乎太明显,但我一直在努力工作,直到我得到你需要包括基本图像


mic*_*ard 11

对于docker> 1.10,我发现了这个问题:https://github.com/docker/docker/issues/20316#issuecomment-221289631

鉴于此Dockerfile

FROM busybox
RUN mkdir this-is-a-test
RUN echo "hello world"
Run Code Online (Sandbox Code Playgroud)

docker build -t caching-test .

然后我们可以看到包含图像的图层 docker history caching-test

3e4a484f0e67        About an hour ago   /bin/sh -c echo "Hello world!"                  0 B                 
6258cdec0c4b        About an hour ago   /bin/sh -c mkdir this-is-a-test                 0 B                 
47bcc53f74dc        9 weeks ago         /bin/sh -c #(nop) CMD ["sh"]                    0 B                 
<missing>           9 weeks ago         /bin/sh -c #(nop) ADD file:47ca6e777c36a4cfff   1.113 MB  
Run Code Online (Sandbox Code Playgroud)

1.11中保存/加载的更改保留了父层和子层之间的关系,但仅当它们通过docker save保存在一起时才会保留.我们可以通过运行看到最终测试图像的父级docker inspect test | grep Parent.

$ docker inspect caching-test | grep Parent
"Parent": "sha256:6258cdec0c4bef5e5627f301b541555883e6c4b385d0798a7763cb191168ce09", 
Run Code Online (Sandbox Code Playgroud)

这是我们的Docker历史输出中的第二个顶层.

要使用保存和加载重新创建缓存,您需要保存所有作为父项引用的图像和图层.实际上,这通常意味着您需要在同一命令中保存每个图层以及FROM图像.

docker save caching-test 6258cdec0c4b busybox > caching-test.tar - 请注意,我们还可以为save命令提供图层名称而不是ID.

让我们清除所有内容,然后从tar文件重新加载图像. docker rmi $(docker images -q).确认不存在图像.

然后跑docker load -i caching-test.tar.如果你看图像,你会看到busybox,然后是缓存测试.运行docker history caching-test将显示与最初构建图像时完全相同的输出.这是因为通过保存和加载保留了父/子关系.您甚至可以运行docker inspect caching-test | grep Parent并查看与父图层给出的完全相同的ID.

并且运行相同Dockerfile的重建将向您显示正在使用缓存.

Sending build context to Docker daemon 5.391 MB
Step 1 : FROM busybox
 ---> 47bcc53f74dc
Step 2 : RUN mkdir this-is-a-test
 ---> Using cache
 ---> 6258cdec0c4b
Step 3 : RUN echo "hello world"
 ---> Using cache
 ---> 3e4a484f0e67
Successfully built 3e4a484f0e67
Run Code Online (Sandbox Code Playgroud)

编辑:下面这个只适用于docker 1.10之前

docker pull theimagefromthefirstdockerfileontheregistry构建新机器之前,您可以在第二台机器上.

这样您就可以确保第二台机器上存在每一层.

docker-engine每次构建一个层时都不会查询注册表(它甚至不知道它),它会太慢/太重,所以我不认为还有另一种方法.

  • 感谢您的回答.我最终在CI环境中这样做了.除了您的回答:可以使用以下命令保存图像的所有可用图层`docker save IMAGE_NAME $(docker history -q IMAGE_NAME | tail -n +2 | grep -v\<missing \> | tr'\n''')> TAR_FILE_NAME.tar`.总而言之,即使我必须存储非常大的工件(这个方法也必须保存,并且此方法不允许重用像注册表那样的推送层),这种解决方法仍然有效.我希望将来Docker能解决这个问题. (2认同)

Jef*_*eff 8

对于 >= 19.03 的 Docker 版本,您可以使用新的 BuildKit 功能来避免在构建之前拉取远程镜像。通过设置 DOCKER_BUILDKIT 环境变量来激活 BuildKit,然后使用 BUILDKIT_INLINE_CACHE 构建参数打开内联缓存以将构建缓存与您的图像一起存储在您的注册表中,如下所示:

export DOCKER_BUILDKIT=1
docker build -t registry/imagename:tag --cache-from registry/imagename:tag --build-arg BUILDKIT_INLINE_CACHE=1 .
docker push registry/imagename:tag
Run Code Online (Sandbox Code Playgroud)

感谢Nicholas Dille提供了这个解决方案。