当输出包含子目录时,Docker BuildKit“上下文被取消”(Docker 4.29 及以上版本)

问题描述 投票:0回答:1

我所在的团队使用多阶段 Docker 文件作为我们的构建引擎,使用 Docker BuildKit 中的 自定义构建输出。我们正在使用适用于 Windows 的 Docker Desktop 和 Linux 容器。

从 Docker 4.29 开始(现在 4.30 中的行为相同),我们遇到了一个问题,只要输出目标包含子目录,构建就会失败并显示

ERROR: failed to solve: error from receiver: context canceled

这是一个

Dockerfile
的最小示例,它展示了该问题:

FROM alpine
WORKDIR /app
RUN mkdir test
RUN touch test/mytestfile

FROM scratch
COPY --from=0 /app .

解释

  1. 初始构建阶段是我们的“构建器”映像(它在名为
    app
    的目录中创建一些构建输出。特别注意,构建输出包含一个名为
    test
    的子目录)
  2. 第二个构建阶段从初始构建阶段的
    /app
    目录中获取构建输出,并将其发送到 Docker BuildKit 的自定义导出器

在上面的示例中,Docker 调用如下所示:

docker build --no-cache --output . .

预期行为

预期的行为是自定义导出器将构建输出发送到本地工作目录,并且文件

test/mytestfile
出现在本地

实际行为

目录

test
已创建,但为空。 Docker 调用自动取消,并显示上述错误消息。完整日志如下:

[+] Building 4.4s (9/9) FINISHED                                                                                                                               docker:default 
 => [internal] load build definition from Dockerfile                                                                                                                     0.0s 
 => => transferring dockerfile: 143B                                                                                                                                     0.0s 
 => [internal] load metadata for docker.io/library/alpine:latest                                                                                                         1.5s 
 => [internal] load .dockerignore                                                                                                                                        0.0s 
 => => transferring context: 2B                                                                                                                                          0.0s 
 => [stage-0 1/4] FROM docker.io/library/alpine:latest@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b                                           2.0s 
 => => resolve docker.io/library/alpine:latest@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b                                                   0.0s 
 => => sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b 1.64kB / 1.64kB                                                                           0.0s 
 => => sha256:6457d53fb065d6f250e1504b9bc42d5b6c65941d57532c072d929dd0628977d0 528B / 528B                                                                               0.0s 
 => => sha256:05455a08881ea9cf0e752bc48e61bbd71a34c029bb13df01e40e3e70e0d007bd 1.47kB / 1.47kB                                                                           0.0s 
 => => sha256:4abcf20661432fb2d719aaf90656f55c287f8ca915dc1c92ec14ff61e67fbaf8 3.41MB / 3.41MB                                                                           1.8s 
 => => extracting sha256:4abcf20661432fb2d719aaf90656f55c287f8ca915dc1c92ec14ff61e67fbaf8                                                                                0.1s 
 => [stage-0 2/4] WORKDIR /app                                                                                                                                           0.1s 
 => [stage-0 3/4] RUN mkdir test                                                                                                                                         0.3s 
 => [stage-0 4/4] RUN touch test/mytestfile                                                                                                                              0.3s 
 => [stage-1 1/1] COPY --from=0 /app .                                                                                                                                   0.0s 
 => CANCELED exporting to client directory                                                                                                                               0.0s 
 => => copying files 56B                                                                                                                                                 0.0s 
ERROR: failed to solve: error from receiver: context canceled

我还尝试过上述的变体:

  • scratch
    图像中显式创建目录(并为其设置权限)
  • 在主机上提前创建输出目录
  • 在 Docker 调用中指定
    --output ./test
  • 不同的最终阶段镜像(尽管我们所有的构建目前都使用
    scratch
    和 Docker 4.28)

结果总是一样的 -

ERROR: failed to solve: error from receiver: context canceled

在 Docker 调用中指定

--progress=plain
不再具有启发性:

...

#9 exporting to client directory
#9 copying files 56B done
#9 CANCELED
ERROR: failed to solve: error from receiver: context canceled

如果我们删除子目录

test
(即将第三条和第四条 Docker 指令替换为
RUN touch mytestfile
),那么结果就是预期的那样 - 在本地工作目录中出现一个名为
mytestfile
的空文件。但不幸的是,在我们的实际用例中,构建输出中的子目录是不可避免的(并且不能轻易重构)。

此外,我发现的一种解决方法是在 Docker 调用中使用

type=tar

docker build --output type=tar,dest=out.tar .

然后生成一个具有预期目录结构的

.tar
文件:

tarball output

如果可能的话,我们宁愿不使用此解决方法,因为它会通过额外的构建步骤来解压

.tar
文件,从而污染我们的构建管道。

有趣的是 - 这种行为似乎是在 Docker 4.29 中引入的(并且在 4.30 中仍然存在)。我们在发行说明中没有看到任何与此相关的明显内容,这让我想知道我们现有的设置是否以某种方式“滥用”了该功能。也许有知情人士可以透露一些信息?

docker dockerfile docker-build docker-buildkit
1个回答
0
投票

这是一个错误,已在 https://github.com/docker/buildx/issues/2433 报告。请按照该问题跟踪修复进度。

© www.soinside.com 2019 - 2024. All rights reserved.