Процедура публикации образа
Процесс публикации образа при обычной работе с 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:4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d
registry.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.0
registry.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
.