diff --git a/docs/_data/sidebars/_documentation.yml b/docs/_data/sidebars/_documentation.yml
index 6e99df9608..d9a8e9dc40 100644
--- a/docs/_data/sidebars/_documentation.yml
+++ b/docs/_data/sidebars/_documentation.yml
@@ -173,12 +173,15 @@ entries:
- title: Сборка
f:
- - title: Обзор (НОВИНКА)
+ - title: Обзор (NEW)
url: /usage/build_draft/overview.html
- - title: Конфигурация образов (НОВИНКА)
+ - title: Конфигурация образов (NEW)
url: /usage/build_draft/images.html
+ - title: Сборочный процесс (NEW)
+ url: /usage/build_draft/building.html
+
- title: Процесс сборки
url: /usage/build/build_process.html
@@ -205,7 +208,7 @@ entries:
- title: В Kubernetes
url: /usage/build/run_in_containers/use_kubernetes.html
- - title: Сборка образов с помощью Stapel (ОБНОВЛЕНИЕ)
+ - title: Сборка образов с помощью Stapel (NEW)
f:
- title: Обзор
url: /usage/build_draft/stapel/overview.html
diff --git a/docs/pages_ru/usage/build_draft/all_in_one.md b/docs/pages_ru/usage/build_draft/all_in_one.md
index 5dd2d57a2b..6a26ce2ea3 100644
--- a/docs/pages_ru/usage/build_draft/all_in_one.md
+++ b/docs/pages_ru/usage/build_draft/all_in_one.md
@@ -1,230 +1,21 @@
-# Vision
-
-- [Vision](#vision)
- - [Обзор](#обзор)
- - [Конфигурация образов](#конфигурация-образов)
- - [Сборочный процесс](#сборочный-процесс)
- - [Параллельная сборка](#параллельная-сборка)
- - [Послойное кеширование в container registry](#послойное-кеширование-в-container-registry)
- - [Автотегирование / тегирование](#автотегирование--тегирование)
- - [Синхронизация](#синхронизация)
- - [Сборочный бэкенд](#сборочный-бэкенд)
- - [Buildah](#buildah)
- - [Системные требования](#системные-требования)
- - [Включение Buildah](#включение-buildah)
- - [Драйвер хранилища](#драйвер-хранилища)
- - [Ulimits](#ulimits)
- - [Работа в контейнерах](#работа-в-контейнерах)
- - [Организация хранилища](#организация-хранилища)
- - [Хранилище](#хранилище)
- - [Именование стадий](#именование-стадий)
- - [Первичный репозиторий](#первичный-репозиторий)
- - [Вторичный репозиторий](#вторичный-репозиторий)
- - [Кэширующий репозиторий](#кэширующий-репозиторий)
- - [Финальный репозиторий](#финальный-репозиторий)
- - [Примеры организации хранилища стадий](#примеры-организации-хранилища-стадий)
- - [1. Стандарт](#1-стандарт)
- - [2. Дополнительный кэш в локальной сети](#2-дополнительный-кэш-в-локальной-сети)
- - [3. Полная оптимизация](#3-полная-оптимизация)
- - [Stapel](#stapel)
-## Обзор
-
-Чтобы доставить приложение в кубы как правило нужно собрать один или несколько образов приложения.
-
-От пользователя требуется предоставить сборочные инструкции в виде Dockerfile или альтернативного сборочного синтаксиса stapel.
-
-Предоставляется простой интерфейс для встараивания в CI/CD pipeline или для локального использования: команда `werf build [--repo REPO]`. Далее werf из коробки без специальной конфигурации берёт на себя всю работу по сборке, предоставляя следующие фичи:
-
-* оркестрация одновременной/параллельной сборки всех образов приложения;
-* общий кеш промежуточных слоёв и образов в Container Registry, доступный с любых раннеров;
-* оптимальная схема тегирования, основанная на содержимом образа, предотвращающая лишние пересборки и downtime приложения при дальнейшем выкате;
-* система обеспечения воспроизводимости и неизменности образов для коммита: однажды собранные образы для коммита более не будут пересобраны (в рамках политик очистки — см. очистка);
+- [Обзор](#обзор)
+- [Конфигурация образов](#конфигурация-образов)
+- [Сборочный процесс](#сборочный-процесс)
+- [Организация хранилища](#организация-хранилища)
+- [Stapel](#stapel)
-После прочтения данного раздела пользователь узнает как описать инструкции сборки образов, как работает механизм сборки, какие есть варианты конфигурации сборочного механизма и варианты организации хранилища под нужды проекта.
+## Обзор
## Конфигурация образов
-
-
## Сборочный процесс
-TODO: как это работает, как конфигурируется: parallel, buildah/docker, режимы buildah, синхронизация+конфигурация
-
-### Параллельная сборка
-
-Параллельная сборка в werf регулируется двумя параметрами `-p, --parallel` и `--parallel-tasks-limit`. По умолчанию параллельная сборка включена и собирается не более 5 образов одновременно.
-
-После построение дерева зависимостей образов, werf разбивает сборку на этапы. Каждый этап содержит набор независимых образов, которые могут собираться параллельно.
-
-```shell
-┌ Concurrent builds plan (no more than 5 images at the same time)
-│ Set #0:
-│ - ⛵ image common-base
-│ - 🛸 artifact jq
-│ - 🛸 artifact libjq
-│ - 🛸 artifact kcov
-│
-│ Set #1:
-│ - ⛵ image base-for-go
-│
-│ Set #2:
-│ - 🛸 artifact terraform-provider-vsphere
-│ - 🛸 artifact terraform-provider-gcp
-│ - 🛸 artifact candictl
-│ - ⛵ image candictl-tests
-│ - 🛸 artifact helm
-│ - 🛸 artifact controller
-│
-│ Set #3:
-│ - ⛵ image base
-│
-│ Set #4:
-│ - ⛵ image tests
-│ - ⛵ image app
-└ Concurrent builds plan (no more than 5 images at the same time)
-```
-
-### Послойное кеширование в container registry
-
-TODO
-Оптимальное использование CR: собрано один раз, больше не пересобирается, конечные образы, слои
-
-### Автотегирование / тегирование
-
-TODO
-
-### Синхронизация
-
-TODO: как работает по умолчанию, как настроить свой сервер
-
-### Сборочный бэкенд
-
-werf поддерживает использование Docker Server или Buildah в качестве бекенда для сборки образов. Buildah поддерживает полноценную работу в контейнерах и послойную сборку Dockerfile-ов с кешированием всех промежуточных слоёв в container registry.
-
-Более подробную информацию о Buildah можно получить в разделе [Режим сборки с использованием Buildah.]({{ "/advanced/buildah_mode.html" | true_relative_url }})
-
-#### Buildah
-
-> ПРИМЕЧАНИЕ: werf поддерживает сборку образов с _использованием Docker-сервера_ или _с использованием Buildah_. Поддерживается сборка как Dockerfile-образов, так и stapel-образов через Buildah.
-
-Для сборки без Docker-сервера werf использует встроенный Buildah в rootless-режиме.
-
-##### Системные требования
-
-TODO: перенести в установку или уже там есть — проверить (?)
-
-Требования к хост-системе для запуска werf в Buildah-режиме без Docker/Kubernetes можно найти в [инструкциях по установке](/installation.html). А для запуска werf в Kubernetes или в Docker-контейнерах требования следующие:
-* Если ваше ядро Linux версии 5.13+ (в некоторых дистрибутивах 5.11+) **рекомендуется** режим работы через модуль ядра `overlay`:
- * Убедитесь, что модуль ядра `overlay` загружен с `lsmod | grep overlay`.
- * Убедитесь, что настройка ядра `CONFIG_USER_NS=y` включена в вашем ядре с помощью `grep CONFIG_USER_NS /boot/config-VERSION`.
- * При использовании ядра в debian-системах команда `sysctl kernel.unprivileged_userns_clone` должна вернуть `1`. В ином случае выполните:
- ```shell
- echo 'kernel.unprivileged_userns_clone = 1' | sudo tee -a /etc/sysctl.conf
- sudo sysctl -p
- ```
- * Команда `sysctl user.max_user_namespaces` должна вернуть по меньшей мере `15000`. В ином случае выполните:
- ```shell
- echo 'user.max_user_namespaces = 15000' | sudo tee -a /etc/sysctl.conf
- sudo sysctl -p
- ```
-* Если ядро более старое или у вас не получается активировать модуль ядра `overlay`, то установите `fuse-overlayfs`, который обычно доступен в репозиториях вашего дистрибутива. В крайнем случае может быть использован драйвер хранилища `vfs`.
-
-##### Включение Buildah
-
-Buildah включается установкой переменной окружения `WERF_BUILDAH_MODE` в один из вариантов: `auto`, `native-chroot`, `native-rootless`. Большинству пользователей для включения режима Buildah достаточно установить `WERF_BUILDAH_MODE=auto`.
-
-* `auto` — автоматический выбор режима в зависимости от платформы и окружения;
-* `native-chroot` работает только в Linux и использует `chroot`-изоляцию для сборочных контейнеров;
-* `native-rootless` работает только в Linux и использует `rootless`-изоляцию для сборочных контейнеров. На этом уровне изоляции werf использует среду выполнения сборочных операций в контейнерах (runc, crun, kata или runsc).
-
-> ПРИМЕЧАНИЕ: На данный момент Buildah доступен только для пользователей Linux и Windows с включённой подсистемой WSL2. Для пользователей MacOS на данный момент предлагается использование виртуальной машины для запуска werf в режиме Buildah.
-
-##### Драйвер хранилища
-
-werf может использовать драйвер хранилища `overlay` или `vfs`:
-
-* `overlay` позволяет использовать файловую систему OverlayFS. Можно использовать либо встроенную в ядро Linux поддержку OverlayFS (если она доступна), либо реализацию fuse-overlayfs. Это рекомендуемый выбор по умолчанию.
-* `vfs` обеспечивает доступ к виртуальной файловой системе вместо OverlayFS. Эта файловая система уступает по производительности и требует привилегированного контейнера, поэтому ее не рекомендуется использовать. Однако в некоторых случаях она может пригодиться.
-
-Как правило, достаточно использовать драйвер по умолчанию (`overlay`). Драйвер хранилища можно задать с помощью переменной окружения `WERF_BUILDAH_STORAGE_DRIVER`.
-
-##### Ulimits
-
-По умолчанию Buildah режим в werf наследует системные ulimits при запуске сборочных контейнеров. Пользователь может переопределить эти параметры с помощью переменной окружения `WERF_BUILDAH_ULIMIT`.
-
-Формат `WERF_BUILDAH_ULIMIT=type:softlimit[:hardlimit][,type:softlimit[:hardlimit],...]` — конфигурация лимитов, указанные через запятую:
-* "core": maximum core dump size (ulimit -c)
-* "cpu": maximum CPU time (ulimit -t)
-* "data": maximum size of a process's data segment (ulimit -d)
-* "fsize": maximum size of new files (ulimit -f)
-* "locks": maximum number of file locks (ulimit -x)
-* "memlock": maximum amount of locked memory (ulimit -l)
-* "msgqueue": maximum amount of data in message queues (ulimit -q)
-* "nice": niceness adjustment (nice -n, ulimit -e)
-* "nofile": maximum number of open files (ulimit -n)
-* "nproc": maximum number of processes (ulimit -u)
-* "rss": maximum size of a process's (ulimit -m)
-* "rtprio": maximum real-time scheduling priority (ulimit -r)
-* "rttime": maximum amount of real-time execution between blocking syscalls
-* "sigpending": maximum number of pending signals (ulimit -i)
-* "stack": maximum stack size (ulimit -s)
-
-### Работа в контейнерах
-
-TODO
-
## Организация хранилища
В данной статье описано, как устроено хранилище собираемых образов в werf, какие бывают типы хранилища, какие функции выполняют эти хранилища, а также различные варианты организации хранилища в проекте.
-### Хранилище
-
-werf собирает образы, состоящие из одной или нескольких стадий. Все стадии собираемых образов сохраняются в так называемое **хранилище стадий** по мере сборки. Хранилище хранит стадии и метаданные проекта. Эти данные могут храниться локально на хост-машине, либо в container registry.
-
-Большинство команд werf требуют указания места размещения _хранилища_ с помощью ключа `--repo` или переменной окружения `WERF_REPO`.
-
-Есть два вида хранилища стадий: **локальное** и **репозиторий** (container registry).
-
-* Локальное хранилище стадий может быть использовано _только для локальной разработки_. В качестве локального хранилища выступает docker server или buildah storage. Локальное хранилище стадий будет задействовано, например, если вызвать команду `werf build` без аргумента `--repo`.
-* Во всех остальных случаях (т.е. кроме локальной разработки) в качестве хранилища стадий всегда выступает репозиторий в container registry. Если запустить сборку с хранилищем стадий в репозитории (например, `werf build` с параметром `--repo ghcr.io/example/myrepo`), то werf сначала проверит наличие требуемых стадий в локальном хранилище и скопирует оттуда подходящие стадии, чтобы не пересобирать эти стадии заново.
-
- **ЗАМЕЧАНИЕ** Каждый проект должен использовать в качестве хранилища уникальный адрес репозитория, который используется только этим проектом.
-
-Стадии будут [именоваться по-разному](#именование-стадий) в зависимости от типа используемого хранилища.
-
-При использовании container registry для хранения стадий, локальный docker-server на всех хостах, где запускают werf, используется как кеш. Этот кеш может быть очищен автоматически самим werf-ом, либо удалён с помощью других инструментов (например `docker rmi`) без каких-либо последствий.
-
-Предполагается, что хранилище стадий инсталляции не может быть удалено или очищено сторонними средствами без негативных последствий для работы werf *(например, см. [первичный репозиторий](#первичный-репозиторий))*. Исключение составляют некоторые типы хранилищ, которые могут быть безопасно удалены в любой момент времени *(например, см. [кэширующий репозиторий](#кэширующий-репозиторий))*.
-
-
-#### Именование стадий
-
-Стадии в _локальном хранилище_ именуются согласно следующей схемы: `PROJECT_NAME:STAGE_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
-```
-
-Стадии в _удалённом хранилище_ именуются согласно следующей схемы: `CONTAINER_REGISTRY_REPO:STAGE_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` — имя проекта;
-- `CONTAINER_REGISTRY_REPO` — репозиторий, заданный опцией `--repo`;
-- `STAGE_DIGEST` — дайджест стадии. Дайджест является идентификатором содержимого стадии и также зависит от истории правок в git репозитории, которые привели к такому содержимому.
-- `TIMESTAMP_MILLISEC` — уникальный идентификатор, который генерируется в процессе [процедуры сохранения стадии]({{ "internals/build_process.html#сохранение-стадий-в-хранилище" | true_relative_url }}) после того как стадия была собрана.
+### Типы хранилища
#### Первичный репозиторий
@@ -473,29 +264,6 @@ application();
$.noConflict();
-<< как это работает
-
-
-
-
-
----
-
->> Организация хранилища
-
-
-
-<< Организация хранилища
-
-
-
-
-
-
-
-
->> Как это работает
-
# Процесс сборки
Сборочный процесс werf для образов, описанных в [werf.yaml]({{ "reference/werf_yaml.html" | true_relative_url }}), подразумевает [последовательную сборку стадий]({{ "internals/stages_and_storage.html" | true_relative_url }}#конвеер-стадий) для описанных образов.
@@ -608,13 +376,8 @@ werf использует алгоритм оптимистичных блоки
<< Как это работает
-
-
-
-
>> Конфигурация сборщика
-
<< Конфигурация сборщика
@@ -678,109 +441,6 @@ werf использует `--synchronization=https://synchronization.werf.io` п
>> Дизайн стапеля
-
-
-
-
-## Артефакты
-
-### Что такое артефакты?
-
-***Артефакт*** — это специальный образ, используемый в других артефактах или отдельных образах, описанных в конфигурации. Артефакт предназначен преимущественно для отделения ресурсов инструментов сборки от процесса сборки образа приложения. Примерами таких ресурсов могут быть — программное обеспечение или данные, которые необходимы для сборки, но не нужны для запуска приложения, и т.п.
-
-Используя артефакты, вы можете собирать неограниченное количество компонентов, что позволяет решать, например, следующие задачи:
-- Если приложение состоит из набора компонент, каждый со своими зависимостями, то обычно вам приходится пересобирать все компоненты каждый раз. Вам бы хотелось пересобирать только те компоненты, которым это действительно нужно.
-- Компоненты должны быть собраны в разных окружениях.
-
-Импортирование _ресурсов_ из _артефактов_ указывается с помощью [директивы import]({{ "advanced/building_images_with_stapel/import_directive.html" | true_relative_url }}) в конфигурации в [_секции образа_]({{ "reference/werf_yaml.html#секция-image" | true_relative_url }}) или _секции артефакта_.
-
-### Конфигурация
-
-Конфигурация _артефакта_ похожа на конфигурацию обычного _образа_. Каждый _артефакт_ должен быть описан в своей секции конфигурации.
-
-Инструкции, связанные со стадией _from_ (инструкции указания [базового образа]({{ "advanced/building_images_with_stapel/base_image.html" | true_relative_url }}) и [монтирования]({{ "advanced/building_images_with_stapel/mount_directive.html" | true_relative_url }})), а также инструкции [импорта]({{ "advanced/building_images_with_stapel/import_directive.html" | true_relative_url }}) точно такие же как и при описании _образа_.
-
-Стадия добавления инструкций Docker (`docker_instructions`) и [соответствующие директивы]({{ "advanced/building_images_with_stapel/docker_directive.html" | true_relative_url }}) не доступны при описании _артефактов_. _Артефакт_ — это инструмент сборки, и все что от него требуется, это — только данные.
-
-Остальные _стадии_ и инструкции описания артефактов рассматриваются далее подробно.
-
-#### Именование
-
-
-```yaml
-artifact: string
-```
-
-
-_Образ артефакта_ объявляется с помощью директивы `artifact`. Синтаксис: `artifact: string`. Так как артефакты используются только самим werf, отсутствуют какие-либо ограничения на именование артефактов, в отличие от ограничений на [именование обычных _образов_]({{ "reference/werf_yaml.html#секция-image" | true_relative_url }}).
-
-Пример:
-```yaml
-artifact: "application assets"
-```
-
-#### Добавление исходного кода из git-репозиториев
-
-
-
-В отличие от обычных _образов_, у _конвейера стадий артефактов_ нет стадий _gitCache_ и _gitLatestPatch_.
-
-> В werf для _артефактов_ реализована необязательная зависимость от изменений в git-репозиториях. Таким образом, по умолчанию werf игнорирует какие-либо изменения в git-репозитории, кэшируя образ после первой сборки. Но вы можете определить зависимости от файлов и папок, при изменении в которых образ артефакта будет пересобираться
-
-Читайте подробнее про работу с _git-репозиториями_ в соответствующей [статье]({{ "advanced/building_images_with_stapel/git_directive.html" | true_relative_url }}).
-
-#### Запуск инструкций сборки
-
-
-
-У артефактов точно такое же как и у обычных образов использование директив и пользовательских стадий — _beforeInstall_, _install_, _beforeSetup_ и _setup_.
-
-Если в директиве `stageDependencies` в блоке git для _пользовательской стадии_ не указана зависимость от каких-либо файлов, то образ кэшируется после первой сборки, и не будет повторно собираться пока соответствующая _стадия_ находится в _stages storage_.
-
-> Если необходимо повторно собирать артефакт при любых изменениях в git, нужно указать _stageDependency_ `**/*` для соответствующей _пользовательской_ стадии. Пример для стадии _install_:
-```yaml
-git:
-- to: /
- stageDependencies:
- install: "**/*"
-```
-
-Читайте подробнее про работу с _инструкциями сборки_ в соответствующей [статье]({{ "advanced/building_images_with_stapel/assembly_instructions.html" | true_relative_url }}).
-
-### Использование артефактов
-
-В отличие от [*обычного образа*]({{ "advanced/building_images_with_stapel/assembly_instructions.html" | true_relative_url }}), у *образа артефакта* нет стадии _git latest patch_. Это сделано намеренно, т.к. стадия _git latest patch_ выполняется обычно при каждом коммите, применяя появившиеся изменения к файлам. Однако *артефакт* рекомендуется использовать как образ с высокой вероятностью кэширования, который обновляется редко или нечасто (например, при изменении специальных файлов).
-
-Пример: нужно импортировать в артефакт данные из git, и пересобирать ассеты только тогда, когда изменяются влияющие на сборку ассетов файлы. Т.е. в случае, изменения каких-либо других файлов в git, ассеты пересобираться не должны.
-
-Конечно, существуют случаи когда необходимо включать изменения любых файлов git-репозитория в _образ артефакта_ (например, если в артефакте происходит сборка приложения на Go). В этом случае необходимо указать зависимость относительно стадии (сборку которой необходимо выполнять при изменениях в git) с помощью `git.stageDependencies` и `*` в качестве шаблона. Пример:
-
-```yaml
-git:
-- add: /
- to: /app
- stageDependencies:
- setup:
- - "*"
-```
-
-В этом случае любые изменения файлов в git-репозитории будут приводить к пересборке _образа артефакта_, и всех _образов_, в которых определен импорт этого артефакта.
-
-**Замечание:** Если вы используете какие-либо файлы и при сборке _артефакта_ и при сборке [*обычного образа*]({{ "advanced/building_images_with_stapel/assembly_instructions.html" | true_relative_url }}), правильный путь — использовать директиву `git.add` при описании каждого образа, где это необходимо, т.е. несколько раз. **Не рекомендуемый** вариант — добавить файлы при сборке артефакта, а потом импортировать их используя директиву `import` в другой образ.
-
-
# Интеграция с SSH-агентом
werf необходим ssh-ключ пользователя в следующих случаях:
diff --git a/docs/pages_ru/usage/build_draft/building.md b/docs/pages_ru/usage/build_draft/building.md
index 3c7eb1b8b2..d2a2cd7513 100644
--- a/docs/pages_ru/usage/build_draft/building.md
+++ b/docs/pages_ru/usage/build_draft/building.md
@@ -3,4 +3,373 @@ title: Сборочный процесс
permalink: usage/build_draft/building.html
---
-
+Запуск сборки в werf осуществляется базовой командой `werf build`.
+
+Команда сборки `werf build` поддерживает работу в локальном режиме без Container Registry, либо в режиме с публикацией образов в Container Registry.
+
+Также сборку могут автоматически осуществлять и другие команды, которые требуют наличия собранных образов в Container Registry, чтобы выполнять свою задачу. Например, выкат приложения через `werf converge`, или запуск произвольной команды в отдельном собранном образе через `werf kube-run`, или рендер манифестов для деплоя в Kubernetes, которые также используют имена собранных образов `werf render` (опционально).
+
+> **ЗАМЕЧАНИЕ:** Парадигма сборки и публикации образов в werf отличается от парадигмы предлагаемой сборщиком docker, в котором есть 2 команды: build и push. В werf есть только команда build, которая собирает образы локально, либо собирает и публикует образы в указанный Container Registry. В секции [послойное кеширование в Container Registry](#послойное-кеширование-в-container-registry) подробно рассмотрен алгоритм работы сборки и чем обусловлено использование такой парадигмы.
+
+## Параллельная сборка
+
+По умолчанию все образы описанные в `werf.yaml` будут собираться параллельно на одном сборочном хосте. При этом если между образами есть какие-то зависимости, то werf автоматически их высчитывает и осуществляет сборку образов в правильном порядке. После построение дерева зависимостей образов, werf разбивает сборку на этапы. Каждый этап содержит набор независимых образов, которые могут собираться параллельно.
+
+Рассмотрим следующий пример:
+
+```Dockerfile
+# backend/Dockerfile
+FROM node as backend
+WORKDIR /app
+COPY package*.json /app/
+RUN npm ci
+COPY . .
+CMD ["node", "server.js"]
+```
+
+```Dockerfile
+# frontend/Dockerfile
+
+FROM ruby as application
+WORKDIR /app
+COPY Gemfile* /app
+RUN bundle install
+COPY . .
+RUN bundle exec rake assets:precompile
+CMD ["rails", "server", "-b", "0.0.0.0"]
+
+FROM nginx as assets
+WORKDIR /usr/share/nginx/html
+COPY configs/nginx.conf /etc/nginx/conf.d/default.conf
+COPY --from=application /app/public/assets .
+COPY --from=application /app/vendor .
+ENTRYPOINT ["nginx", "-g", "daemon off;"]
+```
+
+```yaml
+image: backend
+dockerfile: Dockerfile
+context: backend
+---
+image: frontend
+dockerfile: Dockerfile
+context: frontend
+target: application
+---
+image: frontend-assets
+dockerfile: Dockerfile
+context: frontend
+target: assets
+```
+
+Имеется 3 образа `backend`, `frontend` и `frontend-assets`. Образ `frontend-assets` зависит от `frontend`, потому что он импортирует скомпилированные ассеты из `frontend`.
+
+Формируются следующие наборы для сборки:
+
+```shell
+┌ Concurrent builds plan (no more than 5 images at the same time)
+│ Set #0:
+│ - ⛵ image backend
+│ - ⛵ image frontend
+│
+│ Set #1:
+│ - ⛵ frontend-assets
+└ Concurrent builds plan (no more than 5 images at the same time)
+```
+
+Параллельная сборка в werf регулируется двумя параметрами `--parallel=true` и `--parallel-tasks-limit=5`. По умолчанию параллельная сборка включена и собирается не более 5 образов одновременно.
+
+Отметим что при использовании промежуточных стадий Dockerfile палаллельность их сборки также определяется на основе дерева зависимостей стадий между собой. Также если стадия из одного и того же Dockerfile переиспользуется в разных образах объявленных в `werf.yaml`, то werf обеспечит однократную сборку этой общей стадии без лишних пересборок.
+
+## Хранилище
+
+werf собирает образы, состоящие из набора слоёв. Все слои собираемых образов сохраняются в так называемое **хранилище** по мере сборки.
+
+Большинство команд werf требуют указания места размещения хранилища с помощью ключа `--repo` или переменной окружения `WERF_REPO`.
+
+Есть два вида хранилища: локальное и репозиторий (Container Registry).
+
+**Локальное хранилище** стадий будет задействовано, если вызвать команду `werf build` без аргумента `--repo`. Его можно использовать лишь в рамках локальной машины в ограниченном наборе команд (`werf build` и `werf run`). Такой режим применим, например, для локальной разработки без выката в Kubernetes. В качестве локального хранилища выступает docker server или buildah storage ([см. сборочный бэкенд](#сборочный-бэкенд)).
+
+Для выката приложения в Kubernetes werf предполагает использование режима сборки с публикацией образов в Container Registry — т.н. **хранилище в репозитории**. Такой режим включается при использовании команды `werf build --repo REPO`. В указанный репозиторий сохраняются следующие данные:
+* итоговые образы вместе с кешом промежуточных стадий;
+* служебные метаданные, необходимые для оптимизации сборки, корректной работе алгоритма очистки registry и пр.
+
+> **ЗАМЕЧАНИЕ:** Если запустить сборку с хранилищем стадий в репозитории, то werf сначала проверит наличие требуемых стадий в локальном хранилище и скопирует оттуда подходящие стадии, чтобы не пересобирать эти стадии заново.
+
+Каждый проект должен использовать в качестве хранилища уникальный адрес репозитория, который используется только этим проектом.
+
+Предполагается, что хранилище в репозитории для проекта не будет удалено или очищено сторонними средствами без негативных последствий для пользователей CI/CD построенного на основе werf.
+
+По умолчанию рекомендуется использовать стандартное хранилище в репозитории. В разделе [организация хранилища стадий]({{ "/usage/build_draft/storage.html" | true_relative_url }}) подробно рассмотрены вопросы организации и кастомизации хранилища под нужды проекта.
+
+## Послойное кеширование в Container Registry
+
+В werf реализован алгоритм сборки Dockerfile, который позволяет *уменьшить среднее время сборок* коммитов проекта, а также *обеспечить воспроизводимость собранных образов* для любого коммита проекта (воспроизводимость на любом этапе CI/CD и при откате приложения к произвольному предыдущему коммиту).
+
+В изначальный дизайн алгоритма сборки заложено сохранение сборочного кеша в Container Registry, поэтому из коробки, без специальных настроек обеспечивается:
+* Переиспользование сборочного кеша в распределённом окружении (когда сборка осуществляется с разных хостов).
+* Атомарное сохранение как промежуточных слоёв так и итоговых образов в Container Registry.
+* Гарантия неизменности однажды опубликованных слоёв и итоговых образов в Container Registry.
+
+Алгоритм реализован за счёт отступления от стандартной для docker парадигмы разделения стадий build и push, и переходу к одной стадии build, совмещающей сборку и публикацию слоёв. Стандартный подход сборки и публикации образов и слоёв через docker может выглядеть следующим образом:
+1. Скачивание сборочного кеша из Container Registry (опционально).
+2. Локальная сборка всех промежуточных слоёв образа с использованием локального кеша слоёв.
+3. Публикация собранного образа.
+4. Публикация локального сборочного кеша в Container Registry (опционально).
+
+Алгоритм сборки образов в werf работает по-другому:
+1. Если очередной собираемый слой уже есть в Container Registry, то его сборка и скачивание не происходит.
+2. Если очередной собираемый слой отсутствует в Container Registry, то скачивается предыдущий слой, базовый для сборки текущего.
+3. Новый слой собирается на локальной машине и публикуется в Container Registry.
+4. В момент публикации автоматически разрешаются конфликты между сборщиками с разных хостов, которые пытаются опубликовать один и тот же слой. В этом случае гарантированно будет опубликован только один слой и все остальные сборщики будут обязаны переиспользовать именно его. (Такое возможно за счёт [использования встроенного сервиса синхронизации](#синхронизация-сборщиков)).
+5. И т.д. до тех пор пока не будут собраны все слои образа.
+
+## Тегирование образов
+
+По умолчанию werf автоматизирует процесс тегирования собираемых образов. Любая команда werf, которая требует образов для выполнения своей работы автоматически рассчитывает теги образов для текущего git-коммита, проверяет наличие требуемых тегов в хранилище в репозитории, дособирает нехватающие образы если их там не оказалось.
+
+По умолчанию **тег — это некоторый идентификатор в виде хэша**, включающий в себя контрольную сумму инструкций и файлов сборочного контекста. Например:
+
+```
+registry.example.org/group/project d4bf3e71015d1e757a8481536eeabda98f51f1891d68b539cc50753a-1589714365467 7c834f0ff026 20 hours ago 66.7MB
+registry.example.org/group/project e6073b8f03231e122fa3b7d3294ff69a5060c332c4395e7d0b3231e3-1589714362300 2fc39536332d 20 hours ago 66.7MB
+```
+
+Такой тег будет меняться только при изменении входных данных для сборки образа. Таким образом один тег может быть переиспользован для разных git-коммитов, werf берёт на себя:
+- расчёт таких тегов;
+- атомарную публикацию образов по этим тегам в хранилище;
+- передачу тегов в Helm-чарт.
+
+Образы в репозитории именуются согласно следующей схемы: `CONTAINER_REGISTRY_REPO:DIGEST-TIMESTAMP_MILLISEC`
+
+- `CONTAINER_REGISTRY_REPO` — репозиторий, заданный опцией `--repo`;
+- `DIGEST` — это контрольная сумма от:
+ - сборочных инструкций описанных в Dockerfile или werf.yaml;
+ - файлов сборочного контекста, используемых в тех или иных сборочных инструкциях.
+- `TIMESTAMP_MILLISEC` — временная отметка, которая проставляется в процессе [процедуры сохранения слоя в Container Registry](#послойное-кеширование-в-container-registry) после того как стадия была собрана.
+
+Сборочный алгоритм также дополнительно гарантирует нам, что образ под таким тегом является уникальным и этот тег никогда не будет перезаписан образом с другим содержимым.
+
+### Тегирование промежуточных слоёв
+
+Образы состоят из набора слоёв, каждый слой имеет уникальное имя-идентификатор, а в качестве финального образа используется последний слой .
+TODO
+
+### Получение тегов
+
+Чтобы выгрузить теги всех образов для текущего состояния может использоваться опция `--report-path` для команд `werf build`, `werf converge` и пр.:
+
+```shell
+# по умолчанию формат json
+werf build --report-path=images.json --repo REPO
+
+# поддерживается формат envfile
+werf converge --report-path=images.env --report-format=envfile --repo REPO
+
+werf render --report-path=images.json --repo REPO
+```
+
+> **ЗАМЕЧАНИЕ:** Получить теги заранее, не вызывая сборочный процесс, на данный момент невозможно, можно получить лишь теги уже собранных ранее образов.
+
+Получить теги образов также можно через сервисные значения, передаваемые из сборочного процесса в Helm-чарт, следующей командой:
+
+```shell
+werf helm get-autogenerated-values --repo REPO
+```
+
+### Кастомизация тегов
+
+Несмотря на использование автоматических тегов по умолчанию, имеется возможность добавить дополнительные теги для собираемых образов и использовать их в процессе выката Helm-чарта. Для этого используются опции `--add-custom-tag` — для добавления произвольного количества тегов-алиасов, и опция `--use-custom-tag` — для выбора определённого тега, который будет использоваться в именах образов в Helm-чарте (опция `--use-custom-tag` также неявно добавляет тег-алиас и включает его использование).
+
+```shell
+werf build --repo REPO --add-custom-tag main
+
+# можно добавить несколько тегов-алиасов
+werf build --repo REPO --add-custom-tag main --add-custom-tag latest --add-custom-tag prerelease
+
+# можно добавить несколько тегов и использовать тег "main" для образов в Helm-чарте
+werf converge --repo REPO --add-custom-tag latest --add-custom-tag prerelease --use-custom-tag main
+```
+
+> **ЗАМЕЧАНИЕ:** При использовании опций создаются **дополнительные теги алиасы**, ссылающиеся на автоматические теги-хэши. Полное отключение создания автоматических тегов не предусматривается.
+
+## Синхронизация сборщиков
+
+Сервер синхронизации — это сервисный компонент werf, который предназначен для координации нескольких процессов werf и выполняет роль _менеджера блокировок_. Блокировки требуются для корректной публикации новых образов в Container Registry и реализации алгоритма сборки, описанного в разделе [послойное кеширование в Container Registry](#послойное-кеширование-в-container-registry).
+
+Все команды, использующие параметры хранилища (`--repo=...`) также имеют опцию указания адреса менеджера блокировок, который задается опцией `--synchronization=...` или переменной окружения `WERF_SYNCHRONIZATION=...`. Существует 3 возможных опции для указания типа используемой синхронизации:
+1. Локальный хост. Включается опцией `--synchronization=:local`. Локальный _менеджер блокировок_ использует файловые блокировки, предоставляемые операционной системой.
+2. Kubernetes. Включается опцией `--synchronization=kubernetes://NAMESPACE[:CONTEXT][@(base64:CONFIG_DATA)|CONFIG_PATH]`. _Менеджер блокировок_ в Kubernetes использует ConfigMap по имени проекта `cm/PROJECT_NAME` (тот же самый что и для кеша хранилища) для хранения распределённых блокировок в аннотациях этого ConfigMap. werf использует [библиотеку lockgate](https://github.com/werf/lockgate), которая реализует распределённые блокировки с помощью обновления аннотаций в ресурсах Kubernetes.
+3. Http. Включается опцией `--synchronization=http[s]://DOMAIN`.
+ - Есть публичный сервер синхронизации доступный по домену `https://synchronization.werf.io`.
+ - Собственный http сервер синхронизации может быть запущен командой `werf synchronization`.
+
+werf использует `--synchronization=:local` (локальный _кеш хранилища_ и локальный _менеджер блокировок_) по умолчанию, если используется локальное хранилище (`werf build` без параметра `--repo`).
+
+werf использует `--synchronization=https://synaskjdfchronization.werf.io` по умолчанию, если используется удалённое хранилище (`--repo=CONTAINER_REGISTRY_REPO`).
+
+Пользователь может принудительно указать произвольный адрес компонентов для синхронизации, если это необходимо, с помощью явного указания опции `--synchronization=:local|(kubernetes://NAMESPACE[:CONTEXT][@(base64:CONFIG_DATA)|CONFIG_PATH])|(http[s]://DOMAIN)`.
+
+**ЗАМЕЧАНИЕ:** Множество процессов werf, работающих с одним и тем же проектом обязаны использовать одинаковое хранилище и адрес сервера синхронизации.
+
+### Запуск сервера синхронизации
+
+TODO
+
+## Сборочный бэкенд
+
+werf поддерживает использование Docker Server или Buildah в качестве бекенда для сборки образов. Buildah поддерживает полноценную работу в контейнерах и послойную сборку Dockerfile-ов с кешированием всех промежуточных слоёв в container registry.
+
+TODO
+
+### Buildah
+
+> ПРИМЕЧАНИЕ: На данный момент Buildah доступен только для пользователей Linux и Windows с включённой подсистемой WSL2. Для пользователей MacOS на данный момент предлагается использование виртуальной машины для запуска werf в режиме Buildah.
+
+Для сборки без Docker-сервера werf использует Buildah в rootless-режиме. Buildah встроен в бинарник werf. Требования к хост-системе для запуска werf с бэкендом uildah можно найти в [инструкциях по установке](/installation.html).
+
+Buildah включается установкой переменной окружения `WERF_BUILDAH_MODE` в один из вариантов: `auto`, `native-chroot`, `native-rootless`. Большинству пользователей для включения режима Buildah достаточно установить `WERF_BUILDAH_MODE=auto`.
+
+#### Уровень изоляции сборки
+
+По умолчанию в режиме `auto` werf автоматически выбирает уровень изоляции в зависимости от платформы и окружения.
+
+Поддерживается 2 варианта изоляции сборочных контейнеров:
+1. Chroot — вариант без использования container runtime, включается переменной окружения `WERF_BUILDAH_MODE=native-chroot`.
+2. Rootless — вариант с использованием container runtime (в системе должен быть установлен crun, или runc, или kata, или runsc), включается переменной окружения `WERF_BUILAH_MODE=native-rootless`.
+
+#### Драйвер хранилища
+
+werf может использовать драйвер хранилища `overlay` или `vfs`:
+
+* `overlay` позволяет использовать файловую систему OverlayFS. Можно использовать либо встроенную в ядро Linux поддержку OverlayFS (если она доступна), либо реализацию fuse-overlayfs. Это рекомендуемый выбор по умолчанию.
+* `vfs` обеспечивает доступ к виртуальной файловой системе вместо OverlayFS. Эта файловая система уступает по производительности и требует привилегированного контейнера, поэтому ее не рекомендуется использовать. Однако в некоторых случаях она может пригодиться.
+
+Как правило, достаточно использовать драйвер по умолчанию (`overlay`). Драйвер хранилища можно задать с помощью переменной окружения `WERF_BUILDAH_STORAGE_DRIVER`.
+
+#### Ulimits
+
+По умолчанию Buildah режим в werf наследует системные ulimits при запуске сборочных контейнеров. Пользователь может переопределить эти параметры с помощью переменной окружения `WERF_BUILDAH_ULIMIT`.
+
+Формат `WERF_BUILDAH_ULIMIT=type=softlimit[:hardlimit][,type=softlimit[:hardlimit],...]` — конфигурация лимитов, указанные через запятую:
+* "core": maximum core dump size (ulimit -c)
+* "cpu": maximum CPU time (ulimit -t)
+* "data": maximum size of a process's data segment (ulimit -d)
+* "fsize": maximum size of new files (ulimit -f)
+* "locks": maximum number of file locks (ulimit -x)
+* "memlock": maximum amount of locked memory (ulimit -l)
+* "msgqueue": maximum amount of data in message queues (ulimit -q)
+* "nice": niceness adjustment (nice -n, ulimit -e)
+* "nofile": maximum number of open files (ulimit -n)
+* "nproc": maximum number of processes (ulimit -u)
+* "rss": maximum size of a process's (ulimit -m)
+* "rtprio": maximum real-time scheduling priority (ulimit -r)
+* "rttime": maximum amount of real-time execution between blocking syscalls
+* "sigpending": maximum number of pending signals (ulimit -i)
+* "stack": maximum stack size (ulimit -s)
+
+## Работа в контейнерах
+
+werf поддерживает разные варианты сборки образов при запуске в контейнерах. Рекомендуемым вариантом является использование сборочного бекэнда Buildah, т.к. он не требует внешних зависимостей и прост в настройке. При использовании бекэнда Docker Server будет необходим доступ к серверу Docker и с этим будет связана сложность корректной настройки, а также в этом варианте не будут доступны все возможности werf (см. подробнее далее).
+
+
+Для использования overlayfs в пользовательском режиме без root:
+
+```shell
+docker run \
+ --security-opt seccomp=unconfined --security-opt apparmor=unconfined \
+ registry.werf.io/werf/werf:latest WERF_COMMAND
+```
+
+Если ядро не предоставляет overlayfs для пользовательского режима без root, то следует использовать fuse-overlayfs:
+
+```shell
+docker run \
+ --device /dev/fuse \
+ --security-opt seccomp=unconfined --security-opt apparmor=unconfined \
+ registry.werf.io/werf/werf:latest WERF_COMMAND
+```
+
+Рекомендуется использовать образ `registry.werf.io/werf/werf:1.2-stable`, также доступны следующие образы:
+- `registry.werf.io/werf/werf:latest` — алиас для `registry.werf.io/werf/werf:1.2-stable`;
+- `registry.werf.io/werf/werf:1.2-{alpha|beta|ea|stable|rock-solid}` все образы основаны на alpine, выбираем только канал стабильности;
+- `registry.werf.io/werf/werf:1.2-{alpha|beta|ea|stable|rock-solid}-{alpine|ubuntu|fedora}` — выбираем канал стабильности и базовый дистрибутив.
+
+При использовании этих образов автоматически будет использоваться бэкенд Buildah. Опций для переключения на использование бекэнда Docker Server не предоставляется.
+
+### Работа через Docker Server (не рекомендуется)
+
+> **ЗАМЕЧАНИЕ:** Для этого метода официальных образов с werf не предоставляется, самостоятельно соберите образ с werf, либо перенастройте образ на базе `registry.werf.io/werf/werf` на использование бэкенда Docker Server вместо Buildah.
+
+Для использования локального docker-сервера необходимо примонтировать docker-сокет в контейнер и использовать привилегированный режим:
+
+```shell
+docker run \
+ --privileged \
+ --volume $HOME/.werf:/root/.werf \
+ --volume /tmp:/tmp \
+ --volume /var/run/docker.sock:/var/run/docker.sock \
+ IMAGE WERF_COMMAND
+```
+
+— этот метод поддерживает сборку Dockerfile-образов или stapel-образов.
+
+Для работы с docker-сервером по tcp можно использовать следующую команду:
+
+```shell
+docker run --env DOCKER_HOST="tcp://HOST:PORT" IMAGE WERF_COMMAND
+```
+
+— такой метод поддерживает только сборку Dockerfile-образов. Образы stapel не поддерживаются, поскольку сборщик stapel-образов использует монтирование директорий из хост-системы в сборочные контейнеры.
+
+### Устранение проблем
+
+#### `fuse: device not found`
+
+Полностью данная ошибка может выглядеть следующим образом:
+
+```
+error mounting new container: error mounting build container "53f916e7a334a4bb0d9dbc38a0901718d40b99765002bb7f2f2e5464b1db4294": error creating overlay mount to /home/build/.local/share/containers/storage/overlay/49e856f537ba58afdc09137291133994cd1305e40df72c4fab43077cbd405477/merged, mount_data=",lowerdir=/home/build/.local/share/containers/storage/overlay/l/Z5GEVIFIIQ7H262DYUTX3YOVR6:/home/build/.local/share/containers/storage/overlay/l/PJBBW6UNUNGI37IX6R3LDNPX3J:/home/build/.local/share/containers/storage/overlay/l/MUYSUONLQVE4CJMQVDCH2UBAVQ:/home/build/.local/share/containers/storage/overlay/l/67JHKJDCKBTI4R3Q5S5YG44AD3:/home/build/.local/share/containers/storage/overlay/l/3S72G4SWKDXILGANUOCESP5LDK,upperdir=/home/build/.local/share/containers/storage/overlay/49e856f537ba58afdc09137291133994cd1305e40df72c4fab43077cbd405477/diff,workdir=/home/build/.local/share/containers/storage/overlay/49e856f537ba58afdc09137291133994cd1305e40df72c4fab43077cbd405477/work,volatile": using mount program /usr/bin/fuse-overlayfs: fuse: device not found, try 'modprobe fuse' first
+fuse-overlayfs: cannot mount: No such file or directory
+: exit status 1
+time="2021-12-06T11:30:20Z" level=error msg="exit status 1"
+```
+
+Решение: включите fuse device для контейнера, в котором запущен werf ([подробности](#ядро-linux-без-поддержки-overlayfs-в-режиме-rootless-и-использование-непривилегированного-контейнера)).
+
+#### `flags: 0x1000: permission denied`
+
+Полностью данная ошибка может выглядеть следующим образом:
+
+```
+time="2021-12-06T11:23:23Z" level=debug msg="unable to create kernel-style whiteout: operation not permitted"
+time="2021-12-06T11:23:23Z" level=debug msg="[graphdriver] trying provided driver \"overlay\""
+time="2021-12-06T11:23:23Z" level=debug msg="overlay: mount_program=/usr/bin/fuse-overlayfs"
+Running time 0.01 seconds
+Error: unable to get buildah client: unable to create new Buildah instance with mode "native-rootless": unable to get storage: mount /home/build/.local/share/containers/storage/overlay:/home/build/.local/share/containers/storage/overlay, flags: 0x1000: permission denied
+time="2021-12-06T11:23:23Z" level=error msg="exit status 1"
+```
+
+Решение: отключите профили AppArmor и seccomp с помощью параметров `--security-opt seccomp=unconfined` и `--security-opt apparmor=unconfined`, добавьте специальные аннотации в Pod ([подробности](#ядро-linux-без-поддержки-overlayfs-в-режиме-rootless-и-использование-непривилегированного-контейнера)).
+
+#### `unshare(CLONE_NEWUSER): Operation not permitted`
+
+Полностью данная ошибка может выглядеть следующим образом:
+
+```
+Error during unshare(CLONE_NEWUSER): Operation not permitted
+ERRO[0000] error parsing PID "": strconv.Atoi: parsing "": invalid syntax
+ERRO[0000] (unable to determine exit status)
+```
+
+Решение: отключите профили AppArmor и seccomp с помощью параметров `--security-opt seccomp=unconfined` и `--security-opt apparmor=unconfined`, добавьте специальные аннотации в Pod или используйте привилегированный контейнер ([подробности](#режимы-работы)).
+
+#### `User namespaces are not enabled in /proc/sys/kernel/unprivileged_userns_clone`
+
+Решение:
+```bash
+# Включить непривилегированные user namespaces:
+echo 'kernel.unprivileged_userns_clone = 1' | sudo tee -a /etc/sysctl.conf
+sudo sysctl -p
+```