Docker BuildKit «контекст отменен», если выходные данные содержат подкаталоги (Docker 4.29 и более поздние версии)

Команда, в которой я работаю, использует многоэтапный файл Docker в качестве механизма сборки, используя пользовательские выходные данные сборки из Docker BuildKit. Мы используем Docker Desktop для Windows с контейнерами 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 (и установка для него разрешений)
  • предварительное создание выходного каталога на хосте
  • указание --output ./test при вызове Docker
  • разные образы финальной стадии (хотя сейчас все наши сборки используют scratch с Docker 4.28)

Результат всегда один и тот же - ERROR: failed to solve: error from receiver: context canceled.

Указание --progress=plain в вызове Docker больше не поясняет:

...

#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 в локальном рабочем каталоге. Однако, к сожалению, в наших реальных случаях использования подкаталоги в выходных данных сборки неизбежны (и их невозможно легко удалить с помощью рефакторинга).

Кроме того, я обнаружил один обходной путь — использовать type=tar в вызове Docker:

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

Затем создается файл .tar с ожидаемой структурой каталогов:

Мы бы предпочли не использовать этот обходной путь, если это вообще возможно, так как он загрязняет наши конвейеры сборки дополнительными этапами сборки для распаковки файлов .tar.

Как ни странно, такое поведение, похоже, появилось в Docker 4.29 (и до сих пор присутствует в 4.30). Мы не смогли увидеть ничего очевидного в примечаниях к выпуску, касающихся этого, что заставляет меня задаться вопросом, является ли наша существующая установка каким-то образом «злоупотреблением» этой функцией. Может быть, кто-то из знающих сможет пролить свет?

Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Kubernetes - это портативная, расширяемая платформа с открытым исходным кодом для управления контейнерными рабочими нагрузками и сервисами, которая...
Как создать PHP Image с нуля
Как создать PHP Image с нуля
Сегодня мы создадим PHP Image from Scratch для того, чтобы легко развернуть базовые PHP-приложения. Пожалуйста, имейте в виду, что это разработка для...
1
0
191
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Это ошибка, о которой сообщалось по адресу https://github.com/docker/buildx/issues/2433. Пожалуйста, следите за этой проблемой, чтобы отслеживать ход ее исправления.

Начиная с Docker Desktop 4.32.0 проблема исчезла.

Другие вопросы по теме

Docker «(корневой) Включение дополнительных свойств не разрешено:» при создании базового файла компоновки
Pytest с созданием образа докера из Dockerfile
Dockerfile – как выполнить эхо в файл?
Невозможно отправить запрос на запуск образа Docker. Ошибка сокета зависает в почтальоне. В браузере localhost не отправлял никаких данных
Docker-compose: создание одного и того же контейнера для разных проектов
Когда я пытаюсь построить Docker, я получаю, что каждый из моих проектов csharp не может вычислить кеш (то есть не может быть найден)
Проблема с определением переменных среды в файле Docker Compose
Ошибка модуля PythonNotFound при запуске в контейнере докеров
Для создания Docker-контейнера с определенной версией компилятора необходимо добавить альтернативы обновления в последнюю строку Dockerfile
Есть ли способ автоматически обновить пользовательский интерфейс с помощью Docker Desktop?