Мы разделили сборочный процесс образов, описанных в файле конфигурации werf.yaml на этапы, с четкими функциями и назначением. Каждый такой этап соответствует промежуточному образу, подобно слоям в Docker. В werf такой этап называется стадией, а конечный образ соответствует последней собранной стадии для определённого состояния git и конфигурации werf.yaml.

Стадии — это этапы сборочного процесса. Стадия определяется группой инструкций, указанных в конфигурации. Причем группировка этих инструкций не случайна, имеет определенную логику и учитывает условия и правила сборки. С каждой стадией связан конкретный Docker-образ.

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

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

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

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

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

Дайджест стадии

Дайджест стадии используется для тегирования стадии (дайджест является только частью тега) в хранилище. werf не собирает стадию, если стадия с таким же дайджестом уже находится в хранилище (это поведение похоже на кэширование в Docker, только имеет более сложную логику).

Дайджест стадии — это контрольная сумма от:

  • контрольной суммы зависимостей стадии.
  • дайджеста предыдущей стадии;
  • идентификатора git коммита связанного с предыдущей стадией (если эта стадия связана с git).

Дайджест стадии идентифицирует содержимое стадии и зависит от истории правок в git, которые привели к этому коммиту.

Зависимости стадии

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

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

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

Следующая таблица иллюстрирует зависимости в Dockerfile-образе, 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>
fromArtifact: <artifact 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 importsBeforeInstall

imports before install
import:
- artifact: <artifact 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 importsAfterInstall

imports after install
import:
- artifact: <artifact 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 importsBeforeSetup

imports before setup
import:
- artifact: <artifact 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 importsAfterSetup

imports after setup
import:
- artifact: <artifact 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>

Хранилище

Хранилище хранит стадии и метаданные проекта. Эти данные могут храниться локально на хост-машине, либо в Docker Repo.

Большинство команд werf используют стадии. Такие команды требуют указания места размещения хранилища с помощью ключа --repo или переменной окружения WERF_REPO.

Существует 2 типа хранилища:

  1. Локальное хранилище. Использует локальный docker-server для хранения docker-образов.
  2. Удалённое хранилище. Использует docker registry для хранения docker-образов. Включается опцией --repo=DOCKER_REPO_DOMAIN, например --repo=registry.mycompany.com/web. ЗАМЕЧАНИЕ Каждый проект должен использовать в качестве хранилища уникальный адрес docker repo, который используется только этим проектом.

Стадии будут именоваться по-разному в зависимости от типа используемого хранилища.

При использовании docker registry для хранения стадий, локальный docker-server на всех хостах, где запускают werf, используется как кеш. Этот кеш может быть очищен автоматически самим werf-ом, либо удалён с помощью других инструментов (например docker rmi) без каких-либо последствий.

Заметим, что все команды werf, которые требуют доступа к стадиям должны использовать одно и то же хранилище. Поэтому при использовании локального хранилища все команды werf должны запускаться с одного и того же хоста. При использовании удалённого хранилища не важно с какого хоста запускается werf, если для этих вызовов он общий (касается таких команд как build, converge, cleanup, deploy и т.д.)

Рекомендуется использовать docker registry в качестве хранилища. Werf по умолчанию использует этот режим при работе в CI/CD системах.

Именование стадий

Стадии в локальном хранилище именуются согласно следующей схемы: PROJECT_NAME:DIGEST-TIMESTAMP_MILLISEC. Например:

myproject                   9f3a82975136d66d04ebcb9ce90b14428077099417b6c170e2ef2fef-1589786063772   274bd7e41dd9        16 seconds ago      65.4MB
myproject                   7a29ff1ba40e2f601d1f9ead88214d4429835c43a0efd440e052e068-1589786061907   e455d998a06e        18 seconds ago      65.4MB
myproject                   878f70c2034f41558e2e13f9d4e7d3c6127cdbee515812a44fef61b6-1589786056879   771f2c139561        23 seconds ago      65.4MB
myproject                   5e4cb0dcd255ac2963ec0905df3c8c8a9be64bbdfa57467aabeaeb91-1589786050923   699770c600e6        29 seconds ago      65.4MB
myproject                   14df0fe44a98f492b7b085055f6bc82ffc7a4fb55cd97d30331f0a93-1589786048987   54d5e60e052e        31 seconds ago      64.2MB

Стадии в удалённом хранилище именуются согласно следующей схемы: DOCKER_REPO_ADDRESS:DIGEST-TIMESTAMP_MILLISEC. Например:

localhost:5000/myproject-stages                 d4bf3e71015d1e757a8481536eeabda98f51f1891d68b539cc50753a-1589714365467   7c834f0ff026        20 hours ago        66.7MB
localhost:5000/myproject-stages                 e6073b8f03231e122fa3b7d3294ff69a5060c332c4395e7d0b3231e3-1589714362300   2fc39536332d        20 hours ago        66.7MB
localhost:5000/myproject-stages                 20dcf519ff499da126ada17dbc1e09f98dd1d9aecb85a7fd917ccc96-1589714359522   f9815cec0867        20 hours ago        65.4MB
localhost:5000/myproject-stages                 1dbdae9cc1c9d5d8d3721e32be5ed5542199def38ff6e28270581cdc-1589714352200   6a37070d1b46        20 hours ago        65.4MB
localhost:5000/myproject-stages                 f88cb5a1c353a8aed65d7ad797859b39d357b49a802a671d881bd3b6-1589714347985   5295f82d8796        20 hours ago        65.4MB
localhost:5000/myproject-stages                 796e905d0cc975e718b3f8b3ea0199ea4d52668ecc12c4dbf85a136d-1589714344546   a02ec3540da5        20 hours ago        64.2MB
  • PROJECT_NAME — имя проекта;
  • STAGE_DIGEST — дайджест стадии. Дайджест является идентификатором содержимого стадии и также зависит от истории правок в git репозитории, которые привели к такому содержимому.
  • TIMESTAMP_MILLISEC — уникальный идентификатор, который генерируется в процессе процедуры сохранения стадии после того как стадия была собрана.