Docker Buildx Bake: декларативная сборка мульти-образов через HCL/JSON
В типичном монорепозитории с микросервисами CI-пайплайн содержит десятки команд docker build с разными аргументами, платформами и контекстами. Docker Buildx Bake решает эту проблему — один декларативный файл описывает все сборки, их зависимости и параметры. Разбираем синтаксис HCL, матричные сборки и интеграцию с CI.
Зачем Bake — проблема множества docker build
Без Bake CI-скрипт для 5 сервисов выглядит так:
docker build -f services/api/Dockerfile -t registry/api:v1.2 --platform linux/amd64,linux/arm64 .
docker build -f services/worker/Dockerfile -t registry/worker:v1.2 --platform linux/amd64,linux/arm64 .
docker build -f services/gateway/Dockerfile -t registry/gateway:v1.2 --build-arg ENV=prod .
# ... ещё 10 строк
Проблемы: дублирование параметров, нет параллелизма, сложно поддерживать. Bake заменяет это одной командой:
docker buildx bake --file docker-bake.hcl
docker-bake.hcl — синтаксис
Bake поддерживает HCL (как Terraform), JSON и docker-compose.yml. HCL — самый выразительный формат:
// docker-bake.hcl
variable "TAG" {
default = "latest"
}
variable "REGISTRY" {
default = "ghcr.io/myorg"
}
// Базовый target — общие настройки
target "_common" {
dockerfile = "Dockerfile"
platforms = ["linux/amd64", "linux/arm64"]
args = {
NODE_ENV = "production"
}
}
// Конкретные сервисы наследуют от _common
target "api" {
inherits = ["_common"]
context = "./services/api"
tags = ["${REGISTRY}/api:${TAG}"]
cache-from = ["type=registry,ref=${REGISTRY}/api:cache"]
cache-to = ["type=registry,ref=${REGISTRY}/api:cache,mode=max"]
}
target "worker" {
inherits = ["_common"]
context = "./services/worker"
tags = ["${REGISTRY}/worker:${TAG}"]
}
target "gateway" {
inherits = ["_common"]
context = "./services/gateway"
tags = ["${REGISTRY}/gateway:${TAG}"]
args = {
RATE_LIMIT = "1000"
}
}
// Группа — собрать всё одной командой
group "default" {
targets = ["api", "worker", "gateway"]
}
Ключевые конструкции:
- target — один образ. Поля: context, dockerfile, tags, platforms, args, cache-from/to, output.
- group — набор targets для параллельной сборки.
- variable — параметры, переопределяемые через переменные окружения (
TAG=v2.0 docker buildx bake). - inherits — наследование настроек от другого target (prefix
_= не собирается сам).
Матричные сборки
Bake поддерживает динамическую генерацию targets через функции HCL:
variable "SERVICES" {
default = ["api", "worker", "gateway", "scheduler"]
}
target "service" {
name = "svc-${svc}"
matrix = { svc = SERVICES }
context = "./services/${svc}"
dockerfile = "Dockerfile"
tags = ["${REGISTRY}/${svc}:${TAG}"]
platforms = ["linux/amd64", "linux/arm64"]
}
group "all" {
targets = ["svc-api", "svc-worker", "svc-gateway", "svc-scheduler"]
}
Мульти-платформенная сборка с разными аргументами:
target "api" {
platforms = ["linux/amd64", "linux/arm64"]
args = {
TARGETARCH = BAKE_LOCAL_PLATFORM // встроенная переменная
}
}
// Разные контексты для разных стадий
target "api-test" {
context = "./services/api"
target = "test" // multi-stage: FROM ... AS test
output = ["type=cacheonly"]
}
target "api-prod" {
context = "./services/api"
target = "production"
contexts = { shared = "./libs/shared" } // дополнительный контекст
tags = ["${REGISTRY}/api:${TAG}"]
}
Интеграция с CI — GitHub Actions
# .github/workflows/build.yml
name: Build
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/bake-action@v4
with:
files: docker-bake.hcl
targets: default
push: true
env:
TAG: ${{ github.sha }}
REGISTRY: ghcr.io/${{ github.repository_owner }}
Кэширование — два варианта:
// Registry cache (рекомендуется для CI)
target "api" {
cache-from = ["type=registry,ref=${REGISTRY}/api:cache"]
cache-to = ["type=registry,ref=${REGISTRY}/api:cache,mode=max"]
}
// GitHub Actions cache
target "api" {
cache-from = ["type=gha"]
cache-to = ["type=gha,mode=max"]
}
Bake vs docker-compose build vs Makefile
- docker-compose build — подходит для dev-окружения, но не поддерживает multi-platform, matrix, cache-to registry, параллельную сборку нескольких targets.
- Makefile — гибко, но императивно: нет параллелизма из коробки, дублирование параметров, сложно поддерживать при 10+ сервисах.
- Bake — декларативно, параллельно, с наследованием и переменными. Оптимален для CI с мульти-платформенными сборками.
Bake также умеет читать docker-compose.yml как входной файл — можно мигрировать постепенно:
# Bake прочитает build-секции из compose
docker buildx bake --file docker-compose.yml
Docker Buildx Bake — правильный инструмент для CI-сборки в монорепозиториях: один файл вместо десятков команд, параллельная сборка, кэширование и мульти-платформенность из коробки.