lenec ru

← все посты

Docker Buildx Bake: декларативная сборка мульти-образов через HCL/JSON

15K

В типичном монорепозитории с микросервисами 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-сборки в монорепозиториях: один файл вместо десятков команд, параллельная сборка, кэширование и мульти-платформенность из коробки.

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.