BuildKit: скрытая жемчужина Docker, с помощью которой можно построить практически все

BuildKit: скрытая жемчужина Docker, с помощью которой можно построить практически все


Опубликовано 25 февраля 2026 г. •

5 минут •

912 слов

Большинство людей взаимодействуют с BuildKit каждый день, даже не осознавая этого. когда ты бежишь docker buildBuildKit — это движок, стоящий за этим. Но свести BuildKit к «тому, что собирает Dockerfiles» — это все равно, что называть LLVM «того, что компилирует C». Он продает архитектуру по низким ценам в зависимости от объема.

BuildKit — это подключаемая среда сборки общего назначения. Да, он может генерировать образы OCI, а также архивы, локальные каталоги, пакеты APK, RPM или что-то еще, что вы могли бы описать как направленный ациклический граф операций файловой системы. Dockerfile — это всего лишь интерфейс. Вы можете написать свой собственный.

архитектура

BuildKit имеет чистый дизайн и на удивление имеет смысл при просмотре слоев. Есть три основные концепции.

Бакалавр права: промежуточное представительство

BuildKit лежит в основе бакалавр права (определение низкоуровневой сборки). Думайте об этом как о LLVM IR системы сборки. LLB — это двоичный протокол (protobuf), описывающий DAG операций с файловой системой: запуск команды, копирование файлов, монтирование файловой системы. Он адресуется по содержимому, что означает, что аналогичные операции создают один и тот же хэш, что обеспечивает агрессивное кэширование.

Когда вы пишете Dockerfile, интерфейс Dockerfile анализирует его и выдает LLB. Но ничто в BuildKit не требует, чтобы входные данные были Dockerfile. Любая программа, которая может генерировать действительный LLB, может запускать BuildKit.

Интерфейс: добавьте свой собственный синтаксис

А внешний интерфейс Существует образ контейнера, который BuildKit запускает для преобразования вашего определения сборки (Dockerfile, YAML, JSON, HCL и т. д.) в LLB. Интерфейсная часть получает контекст сборки и файл сборки через API BuildKit Gateway и возвращает упорядоченный граф LLB.

Это ключевой вывод: язык сборки не встроен в BuildKit. Это подключаемый слой. Вы можете написать интерфейс, который считывает спецификацию YAML, конфигурацию TOML или собственный DSL, и BuildKit будет выполнять его так же, как он выполняет Dockerfiles.

Вы уже видели этот механизм раньше. # syntax= Директива в верхней части Dockerfile сообщает BuildKit, какой образ внешнего интерфейса использовать. # syntax=docker/dockerfile:1 Просто по умолчанию. Вы можете указать его на любое изображение.

Решатель и кэш: выполнение с адресацией по содержимому

решатель LLB берет граф и выполняет его. Каждая вершина в DAG имеет адресацию по содержимому, поэтому, если вы уже создали определенный шаг с похожими входными данными, BuildKit полностью его пропускает. Вот почему BuildKit быстрее: он не кэширует слои линейно, как старый Docker Builder. Он кэшируется на уровне операций по всему графу и может параллельно выполнять независимые ветви.

Кэш может быть локальным, встроенным (встроенным в образ) или удаленным (реестр). Это делает BuildKit воспроизводимым и доступным для всех участников CI.

┌─────────────┐    ┌──────────┐    ┌────────┐    ┌─────────┐    ┌────────────┐
│  Your spec  │───▶│ Frontend │───▶│  LLB   │───▶│ Solver  │───▶│   Output   │
│ (YAML, HCL, │    │ (Gateway │    │ (DAG)  │    │ (cache, │    │  (image,   │
│  Dockerfile)│    │  client) │    │        │    │ execute)│    │  tarball,  │
└─────────────┘    └──────────┘    └────────┘    └─────────┘    │ local dir) │
                                                                └────────────┘

не просто изображения

комплект для сборки --output Флаг — это то место, где это становится практичным. Вы можете указать BuildKit экспортировать результаты следующим образом:

  • type=image – Отправить в реестр (по умолчанию для docker build)
  • type=local,dest=./out – Дамп последней файловой системы в локальный каталог
  • type=tar,dest=./out.tar – Экспортировать как tarball
  • type=oci – Экспортировать в архив изображений OCI.

type=local Результат наиболее интересен для случаев использования, не связанных с изображениями. Ваша сборка может генерировать скомпилированные двоичные файлы, пакеты, документацию или что-то еще, а BuildKit сохранит результаты на диск. Образ контейнера не требуется.

Такие проекты, как Earthly, Dagger и Depot, построены на основе LLB Buildkit. Это проверенная закономерность.

Создание пакета APK с пользовательским интерфейсом

Чтобы продемонстрировать это конкретно, я создал APKBuild: собственный интерфейс BuildKit, который считывает спецификацию YAML и генерирует пакеты Alpine APK. Dockerfile не включен. Весь конвейер сборки — от компиляции исходного кода до упаковки APK — выполняется внутри BuildKit с использованием операций LLB. Думайте об этом как о фиктивной версии «Меланжа» Chainguard.

Я выбрал YAML для ознакомления, но спецификация может быть любой, какой вы захотите (JSON, TOML, собственный DSL), если ваш интерфейс может ее проанализировать.

YAML-описание моего пакета выглядит так:

name: hello
version: "1.0.0"
epoch: "0"
url: https://example.com/hello
license: MIT
description: Minimal CMake APK demo

sources:
  app:
    context: {}

build:
  source_dir: hello

Вот и все. Нет Докерфайла. Нет сценария оболочки. BuildKit считывает эту спецификацию через специальный интерфейс и создает .apk файл.

за рулем

Создайте изображение внешнего интерфейса:

docker build -t tuananh/apkbuild -f Dockerfile .

Затем используйте это для создания пакета APK:

cd example
docker buildx build \
  -f spec.yml \
  --build-arg BUILDKIT_SYNTAX=tuananh/apkbuild \
  --output type=local,dest=./out \
  .

Вы должны увидеть пакет APK out папка, как показано ниже

BuildKit: скрытая жемчужина Docker, с помощью которой можно построить практически все

BUILDKIT_SYNTAX Сообщает BuildKit использовать наш собственный интерфейс вместо парсера Dockerfile по умолчанию. --output type=local сбрасывает результат .apk к файлам ./out. Изображение не формируется. Никакой реестр не задействован.

Почему это важно?

BuildKit бесплатно предоставляет вам параллельный кэшированный механизм сборки с адресацией по содержимому. Вам не нужно заново изобретать кэширование, параллелизм или воспроизводимость. Вы пишете интерфейс, который преобразует вашу спецификацию в LLB, а BuildKit делает все остальное.

Это актуально не только для демонстрации игрушек. Dagger использует LLB в качестве механизма выполнения для конвейеров CI/CD. Earthly компилирует Earthfiles в LLB. Модель доведена до совершенства в масштабе.

Если вы создаете инструмент, требующий компиляции кода, создания артефактов или организации многоэтапных сборок, рассмотрите BuildKit в качестве серверной части выполнения. Dockerfile — это просто интерфейс по умолчанию. Реальная мощность находится в двигателе внизу.

Leave a Reply

Your email address will not be published. Required fields are marked *