werf.yaml и два билдера
Что нужно знать перед уроком
- M3.01 — Docker-основы — нужен опыт с обычным Dockerfile и multi-stage
Что нужно знать перед уроком
M3 урок 1 — базовый Dockerfile и multi-stage. Теперь оборачиваем это в конфигурацию werf.yaml, единую для всех образов Application-пакета.
Теория
Структура werf.yaml: project/configVersion + множественные image:-документы
| |
werf.yaml — YAML-документ, разделённый на секции --- (YAML-мультидокумент). Первая секция — общие метаданные проекта (project, configVersion — версия схемы самого конфига, не приложения). Каждая следующая секция, начинающаяся с image:, описывает один собираемый образ. Ключевой момент, критичный для Application с несколькими компонентами (backend+frontend, как у Vikunja, или auth+controlplane): все image:-блоки одного werf.yaml собираются одной командой werf build/werf converge, а связи между ними (кто от кого зависит) описываются директивой dependencies — разбираем в M3 уроке 4.
Dockerfile-builder: dockerfile/context/target
| |
target: — прямой аналог docker build --target — позволяет держать несколько независимых образов в одном multi-stage Dockerfile и выбирать нужный per-image:-блок. Классический пример: один Dockerfile с стадиями FROM node AS frontend-build, FROM golang AS backend-build, FROM nginx AS frontend (target: frontend, копирует статику из frontend-build), FROM alpine AS backend (target: backend, копирует бинарник из backend-build) — четыре стадии, две из которых стадии-инструменты, две — реальные image:-блоки werf.yaml с разными target:.
Выбор Dockerfile-builder оправдан, когда у вас уже есть готовый (или предпочитаемый по стандарту команды) Dockerfile, нет необходимости в тонком контроле кэша по отдельным Git-путям, а инструментарий вокруг Dockerfile (например, hadolint, IDE-подсветка) важен для команды.
Stapel-builder: альтернатива с YAML-инструкциями вместо Dockerfile
| |
Stapel — собственный builder werf, где вместо текста Dockerfile вы описываете шаги как YAML-структуры (shell/ansible-инструкции по user-стадиям — детально в M3 уроке 3). Главное преимущество, которого нет у обычного Dockerfile: более тонкий контроль кэша — можно указать, какие именно файлы Git-репозитория триггерят пересборку конкретной стадии (git.stageDependencies), а не всего образа целиком, как это происходит с COPY в обычном Dockerfile (любое изменение любого скопированного файла инвалидирует весь последующий кэш слоёв Docker-инструкций).
Когда предпочесть какой билдер
| Критерий | Dockerfile-builder | Stapel-builder |
|---|---|---|
Готовый существующий Dockerfile | использовать как есть | нужно переписать под YAML |
| Тонкий контроль кэша по путям Git | нет (только порядок COPY) | да, git.stageDependencies per-стадия |
| Множество вспомогательных образов и импортов между ними | через dependencies+multi-stage | нативная поддержка import (M3 урок 5) |
| Знакомство команды с синтаксисом | Dockerfile — общий стандарт индустрии | YAML, специфичный для werf |
| Ansible-инструкции вместо shell | нет | да (ansible: вместо shell:) |
Для Application-пакетов курса допустимы оба подхода, и часто один и тот же werf.yaml сочетает оба билдера в разных image:-блоках (например, backend через Stapel с тонким кэшем, frontend через готовый Dockerfile от команды фронтенда) — именно такой гибридный подход мы применим для Vikunja.
Частые ошибки и подводные камни
- Забыть
context:при Dockerfile-builder, если Dockerfile не в корне репозитория. По умолчанию context — корень проекта; для монорепозитория сapi//frontend/в разных директориях нужно явно указыватьcontext:для каждогоimage:-блока. - Путать
configVersion(версия схемы werf.yaml) с версией самого Application-пакета.configVersion: 1— это версия формата конфигурации werf, а версия пакета задаётся отдельно черезpackage.yaml(детали — M5 урок 2) и Git-тег. - Пытаться смешать Dockerfile-builder и Stapel-builder в одном
image:-блоке. Каждыйimage:-блок — это либоdockerfile:, либоfrom:+shell:/ansible:, но не оба одновременно; смешение допустимо только между разнымиimage:-блоками одного файла.
Практика в кластере
Практики в кластере в этом уроке нет — фокус на конфигурации сборки, первый деплой собранного Vikunja через Nelm — с M4.
Практика разработки
- В корне клонированного в M3.01 репозитория Vikunja создайте
werf.yaml:
| |
- Проверьте синтаксическую валидность конфигурации без реальной сборки:
| |
- Соберите только backend-образ, указав конкретное имя:
| |
Обратите внимание на вывод — werf показывает прогресс по стадиям (для Dockerfile-builder — по инструкциям Dockerfile, каждая со своим статусом кэша: [USING CACHE] или пересобрана).
Шпаргалка команд урока
| |
Полная шпаргалка werf: 📋 werf — будет пополняться в каждом уроке M3/M8.
Вопросы для самопроверки
target: позволяет держать несколько логических образов в одном multi-stage Dockerfile и выбирать нужную стадию per image:-блок.
Источник: Werf — документация
В обычном Dockerfile любое изменение скопированного файла инвалидирует весь последующий кэш; Stapel позволяет точечно связать маски файлов с конкретными стадиями.
Источник: Werf — документация
Ограничение на единый билдер действует только внутри одного image:-блока; разные image:-блоки одного файла могут использовать разные билдеры.
Источник: Werf — документация — множественные image:-документы
Без явного context: werf использует корень проекта, что для монорепозитория с несколькими компонентами в разных директориях обычно неверно.
Источник: Werf — документация
configVersion описывает версию схемы конфигурационного файла werf, версия пакета задаётся отдельно (package.yaml + Git-тег, M5 урок 2).
Источник: Werf — документация
Рекомендуемая литература
Официальная документация
Статьи и блоги
- werf v1.2 — стабильный релиз утилиты для доставки приложений в Kubernetes (Stapel) — Flant на Habr.
- Первые шаги с werf: собираем и деплоим простое приложение — Flant на Habr.
- GitLab + K8s + Werf — Habr.
Книги
- Nigel Poulton. Docker Deep Dive. 2023. ISBN 978-1916585206.
Связанные материалы
- Предыдущий урок: M3.01 — Docker-основы.
- Следующий урок: M3.03 — Stapel-builder глубоко.
- Шпаргалка: 📋 werf .
✓ Урок пройден — все вопросы самопроверки отвечены верно