Сборка — это процесс который необходимо выполнить werf для сборки образов, указанных в конфигурации.

Dockerfile-образ

werf использует Dockerfile как главный способ описания того, как должен быть собран образ. Образ, собранный из Dockerfile далее будет упоминаться как Dockerfile-образ (более подробно об использовании Dockerfile-образа читай в соответствующем разделе).

Как собирается Dockerfile-образ

Для сборки Dockerfile-образа werf создает единственную стадиюdockerfile.

Как собирается стадия dockerfile:

  1. Высчитывается сигнатура стадии, исходя из указанного Dockerfile и его содержимого. Эта сигнатура отражает состояние собранного образа.
  2. Если образ с такой сигнатурой уже существует в хранилище стадий, то werf не выполняет новую сборку образа.
  3. Если образ с такой сигнатурой отсутствует в хранилище стадий, то werf запускает обычную сборку образа с помощью Docker, используя стандартные команды встроенного в Docker клиента (это аналогично выполнению команды docker build). Кэш, создаваемый при сборке используется как и при обычной сборке без помощи werf.
  4. После сборки стадии, werf помещает ее в хранилище стадий (при этом тегируя соответствующий Docker-образ сигнатурой стадии), если используется параметр --stages-storage :local.

Подробнее о файле конфигурации сборки werf.yaml смотри в соответствующем разделе.

Stapel-образ и Stapel-артефакт

В werf реализован и альтернативный способ сборки образов с использованием т.н. сборщика Stapel. Его особенности:

  • Обеспечивает интеграцию с git и инкрементальную пересборку с учетом истории git-репозитория.
  • Позволяет описывать инструкции сборки с помощью Ansible-заданий.
  • Позволяет использовать между сборками общий кэш, с помощью функционала монтирования.
  • Позволяет уменьшить конечный размер образа, исключая из него исходный код и инструменты сборки.

Образ, собранный с помощью сборщика Stapel далее будет упоминаться как Stapel-образ или Stapel-артефакт в зависимости от контекста.

Читай более подробно про Stapel-образ и Stapel-артефакт в соответствующих разделах.

Как происходит сборка Stapel-образа и Stapel-артефакта

Каждый Stapel-образ и Stapel-артефакт состоит из некоторого количества стадий, для сборки которых используется одинаковая схема.

Чтобы собрать стадию, werf генерирует список инструкций соответствующей стадии. Этот список инструкций зависит от типа стадии и содержит внутренние команды werf и команды, указанные пользователем в конфигурации сборки. Например, werf может добавлять в список инструкций команды применения патча измененных примонтированных файлов (такие патчи werf делает с помощью CLI команд git).

При сборке стадии предполагается что инструкции стадии будут запускаться в контейнере, основанном на предыдущей собранной стадии. Такой контейнер будет упоминаться далее как сборочный контейнер.

werf запускает в сборочном контейнере инструкции из подготовленного списка, и сохраняет результат в хранилище стадий.

werf использует специальный сервисный образ flant/werf-stapel содержащий инструменты и библиотеки, необходимые для сборки Stapel-образа или Stapel-артефакта. Подробнее о самом образе Stapel читай в соответствующей статье.

Сервисный образ flant/werf-stapel монтируется в каждый сборочный контейнер, и все инструменты Stapel доступны при сборке на любой стадии.

Как сборщик Stapel работает с CMD и ENTRYPOINT

Для сборки стадии werf запускает контейнер со служебными значениями CMD и ENTRYPOINT а затем, заменяет их значениями базового образа. Если в базовом образе эти значения не установлены, werf сбрасывает их следующим образом:

  • [] для CMD;
  • [""] для ENTRYPOINT.

Также, werf сбрасывает (использует специальные пустые значения) значение ENTRYPOINT базового образа, если указано значение CMD в конфигурации (docker.CMD).

В противном случае, поведение werf аналогично поведению Docker.

Множественная сборка на одном хосте

Выполнять werf для сборки можно параллельно, в несколько экземпляров одновременно. При сборке стадий, для исключения ситуации одновременной сборки стадии с одной и той же сигнатурой в разных процессах, werf использует механизм установки блокировки. Таким образом, даже при одновременном запуске нескольких сборок, каждая стадия будет собираться только в одном процессе сборки, но стадии с разной сигнатурой могут собираться параллельно.

Если сборочный процесс “наткнется” на блокировку сборки стадии, то он приостановится до снятия блокировки, после чего процесс сборки продолжится.

Такое поведение сделано намерено, т.к. нет смысла собрать параллельно в разных процессах стадию с одинаковой сигнатурой. Достаточно дождаться результата процесса сборки запущенного первым, после чего воспользоваться этим результатом, чтобы сохранить стадию в хранилище стадий.