В werf встроен альтернативный синтаксис описания сборочных инструкций, называемый stapel, который даёт следующие возможности:

  1. Удобство поддержки и параметризации комплексной конфигурации, возможность переиспользовать общие части и генерировать конфигурацию однотипных образов за счет использования YAML-формата и шаблонизации.
  2. Специальные инструкции для интеграции с Git, позволяющие задействовать инкрементальную пересборку с учетом истории Git-репозитория.
  3. Наследование образов и импортирование файлов из образов (аналог multi-stage для Dockerfile).
  4. Запуск произвольных сборочных инструкций, опции монтирования директорий и другие инструменты продвинутого уровня для сборки образов.
  5. Более эффективная механика кеширования слоёв.

Сборка образов через сборщик stapel предполагает описание сборочных инструкций в конфигурационном файле werf.yaml. stapel поддерживается как для сборочного бекенда Docker-сервера (сборка через shell-инструкции или ansible), так и для Buildah (только shell-инструкции).

В данном разделе рассмотрено, как описывать сборку образов с помощью сборщика stapel, а также описание дополнительных возможностей и как ими пользоваться.

Как устроен конвеер стадий stapel

Конвейер стадий — набор условий и правил выполнения стадий, подразумевающий также четко определенный порядок выполнения стадий.

Для каждой стадии werf подсчитывает уникальный сборочный идентификатор — дайджест стадии.

В случае отсутствия у стадии зависимостей она пропускается, и, соответственно, конвейер стадий уменьшается на одну стадию.

Зависимости стадии — это данные, которые напрямую связаны и влияют на дайджест стадии. К зависимостям стадии относятся:

  • файлы (и их содержимое) из Git-репозиториев;
  • инструкции сборки стадии из файла werf.yaml;
  • произвольные строки, указанные пользователем в werf.yaml
  • и т.п.

Большинство зависимостей стадии определяется в файле конфигурации werf.yaml, остальные — во время запуска.

Следующая таблица иллюстрирует зависимости в stapel-образе и stapel-артефакте. Каждая строка таблицы описывает зависимости для определенной стадии. Левая колонка содержит краткое описание зависимостей, правая содержит соответствующую часть werf.yaml и ссылки на разделы с более подробной информацией.

stage dockerfile

target dockerfile instructions
hashsum of files related with ADD and COPY dockerfile instructions
args used in target dockerfile instructions
addHost
image: <image name... || ~>
dockerfile: <relative path>
context: <relative path>
target: <docker stage name>
args:
  <build arg name>: <value>
addHost:
- <host:ip>

stage from

from
or from image stages-digest
or from artifact stages-digest
actual digest from registry (if fromLatest: true)
fromCacheVersion
mounts
from: <image[:<tag>]>
fromLatest: <bool>
fromCacheVersion: <arbitrary string>
fromImage: <image name>
mount:
- from: build_dir
  to: <absolute or relative path>
- from: tmp_dir
  to: <absolute path>
- fromPath: <absolute or relative path>
  to: <absolute path>

stage beforeInstall

beforeInstall bash commands or ansible tasks
cacheVersion
beforeInstallCacheVersion
shell:
  beforeInstall:
  - <bash command>
  cacheVersion: <arbitrary string>
  beforeInstallCacheVersion: <arbitrary string>

or

ansible:
  beforeInstall:
  - <task>
  cacheVersion: <arbitrary string>
  beforeInstallCacheVersion: <arbitrary string>

stage dependenciesBeforeInstall

dependencies before install
import:
- image: <image name>
  before: install
  add: <absolute path>
  to: <absolute path>
  owner: <owner>
  group: <group>
  includePaths:
  - <relative path or glob>
  excludePaths:
  - <relative path or glob>

stage gitArchive

git mappings
git:
- add: <absolute path>
  to: <absolute path>
  owner: <owner>
  group: <group>
  includePaths:
  - <relative path or glob>
  excludePaths:
  - <relative path or glob>
- url: <git repo url>
  branch: <branch name>
  commit: <commit>
  tag: <tag>
  add: <absolute path>
  to: <absolute path>
  owner: <owner>
  group: <group>
  includePaths:
  - <relative path or glob>
  excludePaths:
  - <relative path or glob>

stage install

install bash commands or ansible tasks
installCacheVersion
git files hashsum by install stageDependency
git:
- stageDependencies:
    install:
    - <relative path or glob>

shell:
  install:
  - <bash command>
  installCacheVersion: <arbitrary string>

or

ansible:
  install:
  - <task>
  installCacheVersion: <arbitrary string>

stage dependenciesAfterInstall

dependencies after install
import:
- image: <image name>
  after: install
  add: <absolute path>
  to: <absolute path>
  owner: <owner>
  group: <group>
  includePaths:
  - <relative path or glob>
  excludePaths:
  - <relative path or glob>

stage beforeSetup

beforeSetup bash commands or ansible tasks
beforeSetupCacheVersion
git files hashsum by beforeSetup stageDependency
git:
- stageDependencies:
    beforeSetup:
    - <relative path or glob>

shell:
  beforeSetup:
  - <bash command>
  beforeSetupCacheVersion: <arbitrary string>

or

ansible:
  beforeSetup:
  - <task>
  beforeSetupCacheVersion: <arbitrary string>

stage dependenciesBeforeSetup

dependencies before setup
import:
- image: <image name>
  before: setup
  add: <absolute path>
  to: <absolute path>
  owner: <owner>
  group: <group>
  includePaths:
  - <relative path or glob>
  excludePaths:
  - <relative path or glob>

stage setup

setup bash commands or ansible tasks
setupCacheVersion
git files hashsum by setup stageDependency
git:
- stageDependencies:
    setup:
    - <relative path or glob>

shell:
  setup:
  - <bash command>
  setupCacheVersion: <arbitrary string>

or

ansible:
  setup:
  - <task>
  setupCacheVersion: <arbitrary string>

stage gitCache

size of git diff between last used commit and actual

stage dependenciesAfterSetup

dependencies after setup
import:
- image: <image name>
  after: setup
  add: <absolute path>
  to: <absolute path>
  owner: <owner>
  group: <group>
  includePaths:
  - <relative path or glob>
  excludePaths:
  - <relative path or glob>

stage gitLatestPatch

presence of git diff changes between last used commit and actual

stage dockerInstructions

docker instructions
docker:
  VOLUME:
  - <volume>
  EXPOSE:
  - <expose>
  ENV:
    <env name>: <env value>
  LABEL:
    <label name>: <label value>
  ENTRYPOINT: <entrypoint>
  CMD: <cmd>
  WORKDIR: <workdir>
  USER: <user>
  HEALTHCHECK: <healthcheck>