Все популярные реализации реестров для образов контейнеров поддерживают 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)
- Для удаления версий package приватного репозитория в GitHub используется GraphQL. От пользователя требуется token (
--images-repo-github-token
) со следующими scopes: read:packages, write:packages, delete:packages и repo.
Резюмируя
Мы решили поддерживать следующий набор реализаций 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.
Читайте также в нашем блоге:
- «Content-based tagging в сборщике werf: зачем и как это работает?»;
- «Релиз werf 1.1: улучшения в сборщике сегодня и планы на будущее»;
- «3-way merge в werf: деплой в Kubernetes с Helm „на стероидах“»;
- «Использование werf для выката комплексных Helm-чартов»;
- «Поддержка monorepo и multirepo в werf и при чём здесь Docker Registry».
neumeika
не заметил упоминания nexus, не поясните за него?
aigrychev Автор
Работаем по законам спроса и предложения: проверить все имплементации нет возможности, поэтому наращиваем набор только при должной потребности.
В ближайших планах есть поддержка JFrog Artifactory.
До nexus тоже доберёмся. Спасибо за обратную связь.
P.S. Для многих имплементаций никаких дополнительных обвязок не требуется и всё будет работать по умолчанию (Docker Registry API)
neumeika
спасибо за ответ, попробую, я так понимаю api v2 везде одинаков, хоть я и не вдавался в подробности.
aigrychev Автор
Основных момента два:
Первое можно отрегулировать с помощью опции --images-repo-mode, а вот со вторым или самостоятельно организовывать очистку или добавлять поддержку в werf.
neumeika
а второе не проще политиками делать на стороне реджистри? аля, не качали образ неделю — удаляй, прод образы удаляй только через полгода. Я даже слабо представить могу, как это можно организовать на стороне приложения, которое собирает образы, а не занимается хранением. Хотя, когда пользовался обычным реджистри, штука бы пригодилась, если бы умела делать GC за собой.
Спасибо за ваш труд.
aigrychev Автор
Наш опыт показывает, что регистри не имеет достаточно данных для того, чтобы делать очистку правильно, поэтому необходимо делать это извне и брать в расчёт Git, Kubernetes и ...
В ближайших статьях мы расскажем о нашем подходе, новом алгоритме и основных моментах, которые должны учитываться при очистке.
Пока можно почитать про текущие политики и логику работы в документации.