是否可以缓存多阶段docker构建?

Mat*_*ett 9 containers docker dockerfile google-cloud-build

我最近切换到多阶段docker构建,并且看起来在中间构建上没有任何缓存.我不确定这是否是一个限制器限制,某些东西是不可用的,或者我是否做错了什么.

我在新版本开始时从最终版本中拉出 - 并执行--cache-,但它始终运行完整版本.

小智 23

由于之前的答案已发布,现在有一个使用 BuildKit 后端的解决方案:

这涉及将参数传递--build-arg BUILDKIT_INLINE_CACHE=1给您的docker build命令。您还需要通过设置环境变量来确保使用 BuildKit DOCKER_BUILDKIT=1(在 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
Run Code Online (Sandbox Code Playgroud)

其他一些评论者正在询问docker-compose. 它也适用于此,尽管您需要额外指定环境变量COMPOSE_DOCKER_CLI_BUILD=1以确保 docker-compose 使用 docker CLI(借助 BuildKit DOCKER_BUILDKIT=1),然后您可以BUILDKIT_INLINE_CACHE: 1在YAML 文件的 部分args:部分中设置以确保所需的放。build:--build-arg

以供参考:

  • 我听说它只存储多阶段构建的最新阶段,它真的缓存并重用所有构建步骤吗? (2认同)

Mat*_*ett 18

这似乎是docker本身的限制,并在此问题中进行了描述 - https://github.com/moby/moby/issues/34715

解决方法是:

  1. 使用--target构建中间阶段
  2. 将中间图像推送到注册表
  3. 使用--target构建最终图像并使用多个--cache-from路径,列出所有中间图像和最终图像
  4. 将最终图像推送到注册表
  5. 对于后续构建,首先从注册表中拉出中间+最终图像

  • 如何将其与“docker-compose”一起使用?我有一个缓存的中间阶段图像,我“docker load”并将“cache_from”设置为“docker-compose.yml”中的同一图像,但无论如何它都会重建所有阶段。 (4认同)

Fel*_*oid 8

我想在答案中添加另一个要点

错误的答案

--build-arg BUILDKIT_INLINE_CACHE=1仅缓存最后一层,并且仅在整个 Dockerfile 中没有任何更改的情况下才起作用

因此,要为整个构建启用层缓存,该参数应替换为--cache-to type=inline,mode=max. 查看文档

正确答案

上述 2023 年 3 月 28 日的文档指出:

生成缓存输出时,该--cache-to参数接受一个mode选项,用于定义要包含在导出的缓存中的层。除了缓存之外的所有缓存后端都支持这一点inline

这意味着,对于所有层的缓存中间状态,需要使用registry缓存后端。

我计划使用image:tag与构建时推送相同的内容,但带有后缀-buildcache. 所以,--cache-from type=registry,ref=org/image:tag-buildcache,mode=max --cache-to type=registry,ref=org/image:tag-buildcache,mode=max