image


Все популярные реализации реестров для образов контейнеров поддерживают Docker Registry HTTP API и позволяют использовать одни и те же инструменты для работы с ними. Тем не менее, часть реализаций имеет свои особенности и ограничения, а значит — если вам нужно их поддерживать в своем инструментарии для CI/CD, — с этой спецификой необходимо считаться. Так у нас и случилось в процессе работы над GitOps-утилитой werf, когда мы захотели улучшить в ней то, как обеспечивается жизненный цикл образов.


В статье рассказывается об основных особенностях поддерживаемых имплементаций Docker Registry, а также о соответствующих нововведениях в werf.


Хранение образов


Для хранения Docker-контейнеров, их образов, необходим реестр (registry). Строго говоря, registry — сервис для хранения репозиториев (AWS ECR, Azure CR, Docker Hub и так далее). В репозитории хранятся образы, сгруппированные по имени.


При использовании werf для сборки приложений и/или их деплоя в Kubernetes доступны опции --images-repo и --images-repo-mode, которые позволяют определить, где и как (в одном или нескольких репозиториях*) будут храниться образы приложения в registry.


* Проблематика и история внедрения этой опции описывалась в статье «Поддержка monorepo и multirepo в werf и при чём здесь Docker Registry».


Параметр --images-repo может быть как адресом registry, так и repository. По сути это значение является основой для построения имени образа, а вовсе не обязательно репозиторием, в котором будут храниться образы (шаблоны, описанные ниже, проясняют этот момент).


Для параметра --images-repo-mode поддерживаются два значения, которые определяют шаблон, по которому строится конечное имя образа:


  • IMAGES_REPO:IMAGE_NAME-TAG — шаблон для режима monorepo;
  • IMAGES_REPO/IMAGE_NAME:TAG — шаблон для режима multirepo.

Примечание: при использовании единственного и безымянного образа (image: ~) значение параметра опции --images-repo-mode не имеет никакого смысла, т.к. конечный образ будет всегда использовать значение --images-repo в качестве репозитория (IMAGES_REPO:TAG).


Так как образы не могут храниться в registry, использование режима monorepo совместно с registry не имеет никакого смысла. По этой же причине нельзя использовать безымянный образ (image: ~) и registry, независимо от значения --images-repo-mode.


Поддержка возможных опций


Таким образом, пользователю доступны 3 возможные комбинации значений этих параметров. В таблице ниже представлен список реализаций Docker Registry и поддержка в них этих комбинаций:


реализация registry + multirepo repository + monorepo repository + multirepo
AWS ECR* + + +
Azure CR + + +
Default (DTR) + + +
Docker Hub + + -
GCR + + +
GitHub Packages + + -
GitLab Registry + + +
Harbor + + +
Quay + + -

* В AWS ECR репозитории не создаются автоматически при публикации образа. Требуется создать их вручную (через UI или API) перед использованием.


Как видно по таблице, единственное ограничение распространяется на Docker Hub, GitHub Packages и Quay: в них не поддерживаются многоуровневые имена репозиториев (REGISTRY/REPO/SUBREPO).


Тип реализации, равно как и значение --images-repo-mode, определяется автоматически. Для реализаций, которые поддерживают всё без исключения, multirepo — всегда значения по умолчанию. Значение для остальных имплементаций определяется автоматически по переданному значению --images-repo.


Для того, чтобы задать имя имплементации вручную, можно воспользоваться опцией --implementation. Это может понадобиться, например, если в качестве адреса используется алиас из hosts или необходимо вручную запустить очистку GitLab Registry с помощью werf (при использовании в pipeline ci-env проставит необходимое значение при необходимости).


Иллюстрация


А теперь небольшой пример, который прояснит всё вышесказанное.


Рассмотрим следующий werf.yaml:


project: flant
configVersion: 1
---
image: backend
dockerfile: Dockerfile
target: backend
---
image: frontend
dockerfile: Dockerfile
target: frontend

… и аккаунт на Docker Hub под названием flant.


Параметр --images-repo=flant приведёт к следующим тегам:


  • flant/frontend:tag
  • flant/backend:tag

werf build-and-publish -s=:local -i=flant --tag-custom=tag

Параметр --images-repo=flant/project приведёт к следующим тегам:


  • flant/project:frontend-tag
  • flant/project:backend-tag

werf build-and-publish -s=:local -i=flant/project --tag-custom=tag

Пояснение к werf build-and-publish


Это команда для сборки образов, описанных в werf.yaml, и их последующей публикации в реестре. Используемые параметры:


  • -s — краткая запись опции --stages-storage, которая определяет хранилище стадий (подробнее про зависимость образов от стадий — см. в документации);
  • -i — краткая запись опции --images-repo;
  • --tag-custom — одна из возможных опций тегирования (подробнее про именования и доступные схемы тегирования — в документации).

Очистка образов


Еще одна задача, требующей внимания в контексте реестров образов, — это очистка. Ниже представлена таблица, в которой сопоставлены имплементации и необходимый API для удаления тегов:


Реализация API
AWS ECR Amazon ECR API
Azure CR Azure CR API
Default (DTR) Docker Registry API
Docker Hub Docker Hub API
GCR Docker Registry API
GitHub Packages GitHub GraphQL API (только в приватных git-репозиториях)
GitLab Registry Docker Registry API
Harbor Docker Registry API
Quay Docker Registry API

Для реализаций, поддерживающих удаление тегов с Docker Registry API, достаточно выполнить docker login с токеном, наделенным достаточными полномочиями. А у остальных имплементаций: AWS ECR, Azure CR, Docker Hub и GitHub Packages — неполная поддержка Docker Registry API, поэтому потребуется использовать их API для удаления тегов. При их очистке могут потребоваться дополнительные пользовательские данные.


Особенности


Каковы же особенности использования этих имплементаций при очистке с werf?


  • Для Azure необходимо установить CLI (az) и выполнить авторизацию пользователя с одной из следующих ролей: Owner, Contributor или AcrDelete. Подробности доступны в документации: Azure CR roles and permissions.
  • При удалении тегов из AWS ECR используется AWS SDK. Пользователь может установить AWS CLI и выполнить конфигурацию (aws configure) или просто задать переменные окружения AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY перед выполнением очистки.
  • Для чистки тегов в репозитории Docker Hub werf использует Docker Hub API и для работы требуется token. Пользователь может задать токен* (--images-repo-docker-hub-token) или пользователя с паролем (--images-repo-docker-hub-username + --images-repo-docker-hub-password).

Обратите внимание, что в качестве токена для Docker Hub нельзя использовать personal access token, т.к. удаление ресурсов возможно только при использовании основных учётных данных.


* Используя следующий скрипт, пользователь может получить token самостоятельно:


HUB_USERNAME=USERNAME
HUB_PASSWORD=PASSWORD
HUB_TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{"username": "'${HUB_USERNAME}'", "password": "'${HUB_PASSWORD}'"}' https://hub.docker.com/v2/users/login/ | jq -r .token)


Резюмируя


Мы решили поддерживать следующий набор реализаций Docker Registry в werf:


  • AWS ECR;
  • Azure CR;
  • Docker Hub;
  • Default (DTR);
  • GCR;
  • GitHub Packages;
  • GitLab Registry;
  • Harbor;
  • Quay.

Все они проходят полный цикл тестирования и мы готовы оперативно реагировать на изменения.


Описанные в статье фичи доступны в релизах werf с версии v1.1.9+fix2.


Актуальные изменения и особенности, связанные с поддерживаемыми реализациями Docker Registry, доступны в документации проекта.


P.S.


Читайте также в нашем блоге: