是否可以缓存多阶段 docker 构建?
Posted
技术标签:
【中文标题】是否可以缓存多阶段 docker 构建?【英文标题】:Is it possible to cache multi-stage docker builds? 【发布时间】:2019-03-09 19:42:33 【问题描述】:我最近切换到多阶段 docker 构建,中间构建似乎没有任何缓存。我不确定这是否是 docker 限制、一些不可用的东西或者我做错了什么。
我正在拉下最终构建并在新构建开始时执行 --cache-from,但它始终运行完整构建。
【问题讨论】:
请提供一些输出或日志。为什么你认为没有缓存? @NestorSokil 中间阶段的运行与任何会影响这些 docker 层的更改无关。 docs.docker.com/develop/develop-images/multistage-build/… 的“hello world”甚至做同样的事情。 早期阶段的层不在最终阶段,因此使用--cache-from
对早期阶段没有帮助。保存之前的阶段是可行的,但如果您继续使用相同的计算机/文件系统进行构建,它似乎只能工作并匹配层,因此实际上并不能帮助 CI 构建:(
【参考方案1】:
由于之前的答案已经发布,现在有一个使用 BuildKit 后端的解决方案:https://docs.docker.com/engine/reference/commandline/build/#specifying-external-cache-sources
这涉及将参数 --build-arg BUILDKIT_INLINE_CACHE=1
传递给您的 docker build
命令。您还需要通过设置环境变量DOCKER_BUILDKIT=1
来确保正在使用 BuildKit(在 Linux 上;我认为在使用最新版本的 Docker Desktop 时,BuildKit 可能是 Windows 上的默认后端)。完整的 CI 命令行解决方案可能类似于:
export DOCKER_BUILDKIT=1
# Use cache from remote repository, tag as latest, keep cache metadata
docker build -t yourname/yourapp:latest --cache-from yourname/yourapp:latest --build-arg BUILDKIT_INLINE_CACHE=1 .
# Push new build up to remote repository replacing latest
docker push yourname/yourapp:latest
其他一些评论者正在询问docker-compose
。它也适用于此,尽管您需要另外指定环境变量 COMPOSE_DOCKER_CLI_BUILD=1
以确保 docker-compose 使用 docker CLI(感谢 DOCKER_BUILDKIT=1
使用 BuildKit),然后您可以在 args:
部分设置 BUILDKIT_INLINE_CACHE: 1
build:
部分的 YAML 文件,以确保设置了所需的 --build-arg
。
【讨论】:
【参考方案2】:这似乎是 docker 本身的限制,并在此问题下进行了描述 - https://github.com/moby/moby/issues/34715
解决方法是:
-
使用 --target 构建中间阶段
将中间图像推送到注册表
使用 --target 构建最终映像并使用多个 --cache-from 路径,列出所有中间映像和最终映像
将最终图像推送到注册表
对于后续构建,首先从注册表中拉取中间 + 最终图像
【讨论】:
它使用第一个匹配,因此首先列出最终图像,然后是中间图像。这在 CI 情况下不起作用,您从推送中拉到不同的机器,Docker --cache-from 处理中的一些错误。 github.com/moby/moby/issues/34715 您如何将它与docker-compose
一起使用?我有一个缓存的中间阶段图像,我 docker load
并将 cache_from
设置为 docker-compose.yml
中的同一图像,但无论如何它都会重建所有阶段。以上是关于是否可以缓存多阶段 docker 构建?的主要内容,如果未能解决你的问题,请参考以下文章