Процедура публикации образа
Процесс публикации образа при обычной работе с Docker, состоит из следующих этапов:
docker tag REPO:TAG
docker push REPO:TAG
docker rmi REPO:TAG
- Получение имени или id собранного локального образа.
 - Создание временного образа-псевдонима, состоящего из следующих частей:
    
- имя Docker-репозитория содержащего в том числе и адрес Docker registry;
 - имя Docker-тега.
 
 - Публикация образа-псевдонима в Docker registry.
 - Удаление временного образа-псевдонима.
 
В werf реализована иная логика публикации образа, описанного в конфигурации:
- Создание нового образа с определенным именем на основе соответствующего собранного образа. В созданном образе хранится информация о применяемой схеме тегирования, необходимая для внутреннего использования werf (эта информация сохраняется с использованием docker labels). Далее, такая информация будет упоминаться как мета-информация образа. werf использует мета-информацию образа в процессе деплоя и процессе очистки.
 - Публикация созданного образа в Docker registry.
 - Удаление образа, созданного на этапе 1.
 
Далее, такой процесс будет называться процессом публикации образа.
Результатом процесса публикации образа является образ, именованный согласно правил именования образов и загруженный в Docker registry. Все эти шаги выполняются с помощью команды werf publish или werf build-and-publish.
Именование образов
Во время процесса публикации образа, werf формирует имя образа используя:
- значение параметра 
--images-repo; - значение параметра 
--images-repo-mode; - имя образа из файла конфигурации 
werf.yaml; - значение параметра тегирования.
 
Итоговое имя Docker-образа имеет формат — DOCKER_REPOSITORY:TAG.
Параметры --images-repo и --images-repo-mode определяют адрес хранения образов и формат его имени в репозитории.
Если в конфигурации проекта (файл werf.yaml) описан только один безымянный образ, то значение параметра --images-repo используется в качестве имени Docker-репозитория без изменений. Имя Docker-образа в таком случае будет соответствовать шаблону: IMAGES_REPO:TAG.
Если в конфигурации проекта (файл werf.yaml) описано несколько образов, то шаблон имени Docker-образа будет зависеть от значения параметра --images-repo-mode:
IMAGES_REPO:IMAGE_NAME-TAGв случае значенияmonorepoдля параметра--images-repo-mode;IMAGES_REPO/IMAGE_NAME:TAGв случае значенияmultirepoдля параметра--images-repo-mode(используется по умолчанию).
Большинство реализаций Docker registry позволяют создавать иерархию репозиториев, например, COMPANY/PROJECT/IMAGE.
В этом случае вам нет необходимости менять значение парамера --images-repo-mode со значения по умолчанию — multirepo.
Но, если у вас в проекте описано несколько образов, и вы работаете с Docker registry неподдерживающим иерархию репозиториев (самый яркий пример, это — Docker Hub), то вам потребуется указать значение monorepo в параметре --images-repo-mode.
Подробнее о работе режима monorepo/multirepo можно прочитать в нашей статье.
Значение, указываемое для параметра --images-repo может быть также передано через переменную окружения $WERF_IMAGES_REPO.
Значение, указываемое для параметра --images-repo-mode может быть также передано через переменную окружения $WERF_IMAGES_REPO_MODE. 
Пользователь может использовать различные Docker registry имплементации и некоторые из них имеют ограничения и различные значения по умолчанию для images repo (подробнее о работе с различными Docker registry имплементациями и их особенностях).
Именование образов должно быть одинаковым при выполнении команд publish, build-and-publish, deploy, а также команд процесса очистки. В противном случае вы можете получить не работающий pipeline и потерю образов и стадий по результатам работы очистки
Docker-тег определяется исходя из используемых параметров --tag-*:
| option | description | 
|---|---|
--tag-git-tag TAG | 
      Используется стратегия тегирования git-tag, — тегирование осуществляется по указанному git-тегу | 
--tag-git-branch BRANCH | 
      Используется стратегия тегирования git-branch, — тегирование осуществляется по указанной git-ветке | 
--tag-git-commit COMMIT | 
      Используется стратегия тегирования git-commit, — тегирование осуществляется по указанному хэшу git-коммита | 
--tag-custom TAG | 
      Тегирование осуществляется по указанному произвольному тегу | 
--tag-by-stages-signature | 
      Тегирование каждого образа по сигнатуре стадий этого образа | 
Все передаваемые параметры тегирования валидируются, с учетом стандартных ограничений Docker на содержание имени тега образа. При необходимости, вы можете использовать слагификацию (slug, slugify — преобразование текста к виду, удобному для восприятия человеком) тегов, читай подробнее об этом в соответствующей статье.
Используя параметры --tag-*, вы не просто указываете тег, которым нужно протегировать образ, а также определяете стратегию тегирования. Стратегия тегирования влияет на операцию очистки. В частности, политика очистки выбирается в зависимости от стратегии тегирования, а в случае использования стратегии тегирования по произвольному тегу политика очистки не применяется совсем.
Использование параметров тегирования --tag-git-* подразумевает указание аргументов в виде значений тегов, веток и коммитов git. Все такие параметры разработаны с учетом совместимости с современными CI/CD системами, в которых выполнение задания pipeline CI происходит в отдельном экземпляре git-дерева для конкретного git-коммита, а имена тега, ветки и хэш коммита передаются через переменные окружения (например, для GitLab CI это CI_COMMIT_TAG, CI_COMMIT_REF_NAME и CI_COMMIT_SHA).
Опция --tag-by-stages-signature=true включает метод тегирования образов по их содержимому.
Тегирование по содержимому образа
Werf v1.1 поддерживание тегирование по содержимому образов. Теги результирующих docker-образов зависят от содержимого этих образов.
При использовании команды werf publish --tag-by-stages-signature или werf ci-env --tagging-strategy=stages-signature werf будет тегировать образы по так называемой сигнатуре стадий образа. Каждый образ тегируется своей такой сигнатурой, которая рассчитывается по тем же правилам, что и сигнатуры отдельных стадий образа.
Сигнатура стадий образа зависит от его содержимого и также зависит от истории правок в git репозитории, которые привели к такому содержимому.
В целом в таких системах контроля версий как git бывают холостые коммиты в репозиторий, которые не должны менять результирующий образ. Например, это могут быть пустые коммиты, merge-коммиты или коммиты, изменяющие файлы, которые не попадают в результирующий образ.
При тегировании образов например по git-коммитам эти холостые коммиты будут заставлять werf создавать новые имена образов, даже если содержимое этих образов не поменялось. А новые имена образов в свою очередь вызовут перезапуски Pod’ов приложения в Kubernetes, что уже является совсем нежелательным эффектом. В целом данный момент препятствует хранению множества сервисов в едином git репозитории.
Сигнатура стадий же напротив не будет меняться при создании таких холостых коммитов, и не будет вызывать перезапуски Pod’ов приложения в Kubernetes, при этом она как и commit-id остается связана с историей правок в git и отражает содержимое файлов.
Также можно сказать, что тегирование по сигнатуре стадий является более надежным методом тегирования, нежели тегирование по git-веткам, потому что содержимое результирующего образа не зависит от порядка запуска и выполнения задач в CI/CD системе. Сигнатура стадий приводит к стабильным неизменяемым образам, имя которых является адресом определенного содержимого этих образов.
Чтобы получить корректные имена образов в конфигурации деплоя необходимо использовать шаблон генерации имени образа werf_container_image.
Stages-signature — это стратегия тегирования образов по умолчанию в werf и является единственным рекомендуемым выбором. Стратегии тегирования также объясняются в статьях про интеграцию werf в CI/CD системы.
Объединение параметров
Любые параметры тегирования могут использоваться одновременно в любом порядке при выполнении команды werf publish или werf build-and-publish. В случае передачи нескольких параметров тегирования, werf создает отдельный образ на каждый переданный параметр тегирования, согласно каждому описанному в конфигурации проекта образу.
Примеры
Тегирование образов по содержимому
Имеем файл конфигурации werf.yaml с описанными двумя образами  — backend и frontend.
Выполнение команды:
werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-by-stages-signature
приведет к созданию следующих образов соответственно:
registry.hello.com/web/core/system/backend:4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386dregistry.hello.com/web/core/system/frontend:f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6
где 4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d — это сигнатура стадий образа backend и
f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6 — это сигнатура стадий образа frontend.
Эти теги зависят от содержимого образа и от истории правок в git, которые к этому содержимому привели. Каждая из этих сигнатур будет менятся при создании новых образов, поэтомe пользователь должен корректно обновлять манифесты конфигурации Kubernetes.
Два образа для одного git-тега
Имеем файл конфигурации werf.yaml с описанными двумя образами  — backend и frontend.
Выполнение команды:
werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-git-tag v1.2.0
приведет к созданию следующих образов соответственно:
registry.hello.com/web/core/system/backend:v1.2.0registry.hello.com/web/core/system/frontend:v1.2.0
Два образа для git-ветки
Имеем файл конфигурации werf.yaml с описанными двумя образами  — backend и frontend.
Выполнение команды:
werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-git-branch my-feature-x
приведет к созданию следующих образов соответственно:
registry.hello.com/web/core/system/backend:my-feature-x;registry.hello.com/web/core/system/frontend:my-feature-x.
Два образа для git-ветки, в названии которой есть специальные символы
Имеем файл конфигурации werf.yaml с описанными двумя образами  — backend и frontend.
Выполнение команды:
werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-git-branch $(werf slugify --format docker-tag "Features/MyFeature#169")
приведет к созданию следующих образов соответственно:
registry.hello.com/web/core/system/backend:features-myfeature169-3167bc8c;registry.hello.com/web/core/system/frontend:features-myfeature169-3167bc8c.
Обратите внимание, что команда werf slugify генерирует значение, допустимое для использования в качестве Docker-тега. Читайте подробнее про команду slug в соответствующем разделе.
Тегирование образов по содержимому в GitLab CI
Имеем файл конфигурации werf.yaml с описанными двумя образами  — backend и frontend. Имеем проект web/core/system в GitLab, и сконфигурированный Docker registry для проекта — registry.hello.com/web/core/system.
Запуск следующей команды в задании pipeline GitLab CI (для любой git-ветки или тега — не важно):
type werf && source $(werf ci-env gitlab --verbose --as-file)
werf publish --stages-storage :local
приведет к созданию следующих образов соответственно:
registry.hello.com/web/core/system/backend:4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d;registry.hello.com/web/core/system/frontend:f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6.
где 4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d — это сигнатура стадий образа backend и
f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6 — это сигнатура стадий образа frontend.
Опция --tagging-strategy=stages-signature не была указана, потому что она используется по умолчанию.
Эти теги зависят от содержимого образа и от истории правок в git, которые к этому содержимому привели. Каждая из этих сигнатур будет менятся при создании новых образов, поэтому пользователь должен корректно обновлять манифесты конфигурации Kubernetes.
Два образа в задании GitLab CI
Имеем файл конфигурации werf.yaml с описанными двумя образами  — backend и frontend. Имеем проект web/core/system в GitLab, и сконфигурированный Docker registry для проекта — registry.hello.com/web/core/system.
Запуск следующей команды в задании pipeline GitLab CI для ветки core/feature/ADD_SETTINGS:
type werf && source $(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose --as-file)
werf publish --stages-storage :local
приведет к созданию следующих образов соответственно:
registry.hello.com/web/core/system/backend:core-feature-add-settings-df80fdc3;registry.hello.com/web/core/system/frontend:core-feature-add-settings-df80fdc3.
Обратите внимание, что werf автоматически применяет слагификацию к Docker-тегу core/feature/ADD_SETTINGS, — он будет конвертирован в тег core-feature-add-settings-df80fdc3. Эта конвертация выполняется при вызове команды werf ci-env, которая определяет название ветки из переменных окружения задания GitLab CI, слагифицирует его и заносит результат в переменную окружения WERF_TAG_GIT_BRANCH (альтернативный путь установки значения параметра --tag-git-branch). Читайте подробнее про команду slug в соответствующем разделе.
Безымянный образ в задании GitLab CI
Имеем файл конфигурации werf.yaml с описанным безымянным образом. Имеем проект web/core/queue в GitLab, и сконфигурированный Docker registry для проекта — registry.hello.com/web/core/queue.
Запуск следующей команды в задании pipeline GitLab CI для тега v2.3.1:
type werf && source $(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose --as-file)
werf publish --stages-storage :local
приведет к созданию образа registry.hello.com/web/core/queue:v2.3.1.