Перейти к содержимому

Образы контейнеров ​

Каждый репозиторий Arkvory одновременно служит реестром контейнеров. Docker, Podman, Buildx, containerd, Helm и ORAS отправляют в него данные и забирают их по протоколу OCI Distribution. Слои образов и манифесты хранятся как обычные артефакты. Права на репозиторий, квоты, проверки SHA-256, резервные копии и зеркала действуют для них так же, как для любого другого файла.

Прежде чем начать ​

Вам понадобятся:

  • Адрес сервера с HTTPS и доверенным сертификатом, например arkvory.example. См. HTTPS.
  • Репозиторий, например releases.
  • Ключ: персональный токен доступа или ключ сервиса. См. Учётные записи и ключи.

Реестр отвечает в корне хоста, по адресу /v2/. Он не может работать под префиксом пути, например https://example.com/arkvory/, потому что Docker такие префиксы не поддерживает. Обратный прокси-сервер должен передавать /v2/ без изменений и не должен буферизовать тела запросов. В nginx задайте client_max_body_size 0 и отключите буферизацию запросов.

Имена образов ​

Ссылка на образ имеет такой вид:

text
<хост>/<репозиторий>/<образ>:<тег>
<хост>/<репозиторий>/<образ>@sha256:<дайджест>

Первый сегмент пути — это репозиторий Arkvory. Он служит границей доступа: ключ видит только те репозитории, к которым ему выдан доступ. Остальное — имя образа из одного или нескольких компонентов.

СсылкаРепозиторийОбразЧасть ссылки
arkvory.example/releases/web:1.4releaseswebтег 1.4
arkvory.example/releases/team/web:1.4releasesteam/webтег 1.4
arkvory.example/qa/tools/builder@sha256:…qatools/builderдайджест
ЧастьПравило
РепозиторийСтрочные латинские буквы, цифры, _ и -. Начинается с буквы или цифры. До 64 символов.
ОбразКомпоненты, разделённые /. Компонент состоит из строчных латинских букв и цифр, соединённых ., _, __ или дефисами. Всего до 200 символов.
ТегБуквы, цифры, _, . и -. Начинается с буквы, цифры или _. До 128 символов.
Дайджестsha256: и 64 строчные шестнадцатеричные цифры. Другие алгоритмы отклоняются.

Ссылка без части с именем образа, например arkvory.example/web:1.4, отклоняется с ошибкой NAME_INVALID: web принимается за репозиторий, а имя образа остаётся пустым.

Вход ​

Реестр принимает ключ Arkvory как пароль при аутентификации HTTP Basic. Имя пользователя не проверяется: используйте любое имя, например название задания CI. Запрос может также передавать ключ как Authorization: Bearer <ключ>. Отдельная служба токенов не нужна.

bash
docker login arkvory.example -u ci --password-stdin < ~/.arkvory/key
powershell
Get-Content C:\Private\arkvory.key | docker login arkvory.example -u ci --password-stdin

Остальные клиенты входят так же:

bash
podman login arkvory.example -u ci --password-stdin < ~/.arkvory/key
helm registry login arkvory.example -u ci --password-stdin < ~/.arkvory/key
oras login arkvory.example -u ci --password-stdin < ~/.arkvory/key
КлючДля чего
Персональный токен доступа, область readСкачивание (pull) на рабочей станции
Персональный токен доступа, область read-writeОтправка (push) с рабочей станции
Ключ сервисаCI/CD и агенты развёртывания. Единственный вид ключа, который может удалять образы.
Файловый ключ из файла ключей сервераВладелец установки и прежние интеграции (read или write)

Персональный токен истекает. После этого каждый запрос получает 401 UNAUTHORIZED: создайте новый токен и войдите снова. Docker сохраняет ключ в ~/.docker/config.json, если не настроен помощник учётных данных. Защитите этот файл или используйте хранилище учётных данных.

Push и pull ​

bash
docker tag web:1.4 arkvory.example/releases/team/web:1.4
docker push arkvory.example/releases/team/web:1.4
docker pull arkvory.example/releases/team/web:1.4
docker pull arkvory.example/releases/team/web@sha256:<дайджест>

Что делает реестр:

  • Слой, который уже есть в репозитории, не сохраняется повторно, даже если его использует другой образ.
  • Слои не используются совместно разными репозиториями. Запрос на подключение (mount) слоя из другого репозитория получает обычную сессию загрузки, поэтому клиент отправляет слой заново.
  • Каждый слой и каждый манифест проверяется по дайджесту SHA-256. При несовпадении ничего не сохраняется, а в ответ приходит DIGEST_INVALID.
  • Манифест принимается, только если всё, на что он ссылается, уже есть в репозитории: конфигурация и слои образа или платформенные манифесты индекса. Платформенные манифесты должны находиться в том же образе, что и их индекс. Иначе ответ — MANIFEST_BLOB_UNKNOWN.
  • Скачивание слоёв поддерживает запросы Range.

Реестр принимает такие типы манифестов:

Тип носителя (media type)Для чего
application/vnd.oci.image.manifest.v1+jsonОбразы OCI, чарты Helm, артефакты ORAS
application/vnd.oci.image.index.v1+jsonМультиплатформенные образы, кэш реестра BuildKit
application/vnd.docker.distribution.manifest.v2+jsonОбразы Docker (schema 2)
application/vnd.docker.distribution.manifest.list.v2+jsonМультиплатформенные образы Docker

У манифеста schemaVersion: 2, и его размер не превышает 4 МиБ. Docker schema 1 не поддерживается. Тип берётся из заголовка Content-Type или из поля mediaType манифеста, и они должны совпадать. Pull возвращает манифест в точности таким, каким его отправили (push), с его собственным типом носителя. Реестр не преобразует форматы друг в друга.

Мультиплатформенные образы ​

bash
docker buildx build --platform linux/amd64,linux/arm64 \
  -t arkvory.example/releases/team/web:1.4 --push .

Buildx отправляет каждый платформенный манифест по его дайджесту, затем индекс под тегом. Все они попадают в одно имя образа, как того требует реестр.

Кэш сборки ​

Сборщик BuildKit, который умеет экспортировать кэш, например сборщик docker buildx с драйвером docker-container, может хранить свой кэш реестра в Arkvory:

bash
docker buildx build \
  --cache-from type=registry,ref=arkvory.example/releases/team/web:cache \
  --cache-to type=registry,ref=arkvory.example/releases/team/web:cache,mode=max \
  -t arkvory.example/releases/team/web:1.4 --push .

Индекс кэша перечисляет слои и конфигурацию кэша. Arkvory хранит их как блобы образа и защищает так же, как слои любого сохранённого манифеста.

Чарты Helm ​

Helm хранит чарты как артефакты OCI. После helm registry login:

bash
helm push web-1.4.0.tgz oci://arkvory.example/releases/charts
helm pull oci://arkvory.example/releases/charts/web --version 1.4.0
helm install web oci://arkvory.example/releases/charts/web --version 1.4.0

Чарт становится образом charts/web с тегом 1.4.0 в репозитории releases. Классического репозитория чартов с файлом index.yaml в Arkvory нет.

Артефакты ORAS ​

ORAS хранит любые файлы как слои манифеста OCI:

bash
oras push arkvory.example/releases/tools/settings:1.0 ./settings.json:application/json
oras pull arkvory.example/releases/tools/settings:1.0

Referrers API недоступен: /v2/<имя>/referrers/<дайджест> отвечает 404. Клиенты, которые следуют спецификации OCI, например ORAS, тогда хранят присоединённые артефакты под тегами, названными по дайджесту.

Теги и дайджесты ​

  • Отправка манифеста под тегом перемещает тег. Манифест, на который тег указывал раньше, остаётся в реестре, и его по-прежнему можно скачать по дайджесту.
  • Отправка по дайджесту (PUT /v2/<имя>/manifests/sha256:…) сохраняет манифест без тега. Дайджест должен быть SHA-256 тела запроса.
  • Теги перечисляются в порядке байтов, поэтому прописные буквы идут перед строчными.

Получите список тегов образа:

bash
curl -fsS -u "ci:$ARKVORY_KEY" https://arkvory.example/v2/releases/team/web/tags/list

Ответ — {"name": "releases/team/web", "tags": [...]}. Параметр n задаёт размер страницы (по умолчанию 100, не более 1000), а last — последний тег предыдущей страницы. Если тегов больше, заголовок Link содержит адрес следующей страницы.

Узнайте дайджест тега:

bash
curl -fsSI -u "ci:$ARKVORY_KEY" \
  https://arkvory.example/v2/releases/team/web/manifests/1.4 | grep -i docker-content-digest

Каталога всех образов (/v2/_catalog) нет. В консоли слои и манифесты видны среди артефактов репозитория с меткой oci и названы по своему дайджесту. Чтобы показать их, используйте Фильтр по метке в разделе Артефакты.

Удаление образов и освобождение места ​

Образы удаляются через API реестра. В командной строке Docker для этого нет команды: используйте curl, oras manifest delete или другой инструмент для работы с реестром.

ЗапросДействие
DELETE /v2/<имя>/manifests/<тег>Удаляет только тег. Манифест остаётся, его можно скачать по дайджесту.
DELETE /v2/<имя>/manifests/<дайджест>Удаляет манифест и каждый тег, который на него указывает
DELETE /v2/<имя>/blobs/<дайджест>Отклоняется с кодом 405. Слои уходят вместе со своими манифестами.

Для обоих видов удаления нужен ключ сервиса с действием artifact.delete в репозитории. Персональные токены, сессии консоли и файловые ключи удалять образы не могут. Удаление отвечает кодом 202.

bash
curl -fsS -X DELETE -H "Authorization: Bearer $ARKVORY_CLEANUP_KEY" \
  https://arkvory.example/v2/releases/team/web/manifests/sha256:<дайджест>

Как освобождается место:

  1. Пока манифест хранится, с тегом или без него, Arkvory защищает его и каждый слой, на который он ссылается. Правила хранения пропускают их с причиной блокировки reference.
  2. Перемещение или удаление тега ничего не освобождает. Старые манифесты сохраняют свои слои, пока вы не удалите эти манифесты по дайджесту.
  3. После удаления манифеста по дайджесту его артефакт и слои, которые не использует ни один другой манифест, теряют эту защиту. Они остаются в хранилище, пока их не удалят правила хранения или пока кто-то не удалит их как артефакты. См. Хранение.
  4. Слой, отправленный без манифеста, например при неудачном push, не защищён.
  5. Если удалённый слой снова понадобится, реестр сообщит, что он неизвестен, и следующий push загрузит его заново.

Права ​

Персональные токены и файловые ключи получают доступ к репозиторию на чтение или на запись. Ключи сервисов получают точные действия.

ОперацияДействия ключа сервисаПерсональный токен или файловый ключ
Скачивание манифестов и слоёв (pull)content.readДоступ на чтение
Список теговartifact.listДоступ на чтение
Отправка (push)upload.create, upload.write, upload.completeДоступ на запись; токену нужна область read-write
Удаление тега или манифестаartifact.deleteНевозможно

Ключ CI, который отправляет образы, обычно и скачивает их, например базовые образы или кэш сборки. Дайте ему также content.read и artifact.list. Репозиторий, к которому у ключа нет доступа, отвечает 403 DENIED.

Шлюзы чтения и зеркала ​

  • Шлюз чтения обслуживает pull. Push получает 405.
  • Зеркало получает образы своего источника вместе с их тегами и удалениями. Клиенты скачивают образы с зеркала по его собственному адресу. Push получает 409 DENIED с причиной mirror_read_only.

Ограничения ​

ОграничениеЗначение
Размер манифеста4 МиБ
Размер слояНаибольший объект установки, ARKVORY_MAX_OBJECT_BYTES (по умолчанию около 10 ТиБ)
Один запрос загрузкиДолжен завершиться за 30 минут и не должен простаивать более 30 секунд (ARKVORY_UPLOAD_DEADLINE_MS, ARKVORY_UPLOAD_IDLE_TIMEOUT_MS). 30 минут — это также наибольшее допустимое значение.
Незавершённая загрузкаУдаляется вместе с байтами после 24 часов без активности
Временное место на дискеДо удвоенного размера слоя во время загрузки
Одновременные загрузкиПо умолчанию 1 на ключ и 2 на сервер (ARKVORY_MAX_UPLOADS_PER_PRINCIPAL, ARKVORY_MAX_UPLOADS). Ожидающий запрос сдаётся через 20 секунд (ARKVORY_TRANSFER_QUEUE_TIMEOUT_MS).
Одновременные скачиванияПо умолчанию 4 на ключ и 16 на сервер
Тегов на странице1000
КвотаСлои, манифесты и байты незавершённых загрузок учитываются в квоте репозитория и в ёмкости установки

Docker отправляет каждый слой одним запросом. Поэтому слой должен прийти в пределах срока загрузки, а неудачная загрузка слоя начинается заново с первого байта. Для файлов размером во много гигабайт используйте вместо этого arkvoryctl: он загружает файл по частям и продолжает после сбоя. Переменные описаны в разделе Переменные окружения.

Что не поддерживается ​

  • Referrers API. Он отвечает 404, и клиенты переходят на теги.
  • Каталог всех образов, /v2/_catalog.
  • Подключение (mount) слоёв из другого репозитория. Клиент загружает слой заново.
  • Служба токенов для токенов Bearer. Отправляйте сам ключ через Basic или Bearer.
  • Кэш pull-through для Docker Hub и других реестров.
  • Манифесты Docker schema 1 и дайджесты, отличные от sha256.
  • Удаление отдельных слоёв.
  • Раздел для образов в консоли.

Обычный HTTP для тестов ​

Docker отказывается работать с реестром без HTTPS. По умолчанию по обычному HTTP работают только адреса локального компьютера (localhost, 127.0.0.0/8). Для тестового сервера на другом хосте добавьте его в insecure-registries в конфигурации демона Docker (/etc/docker/daemon.json в Linux) и перезапустите Docker:

json
{
  "insecure-registries": ["arkvory.test:8080"]
}

В Podman для этого служит параметр --tls-verify=false. По обычному HTTP ключ передаётся открытым текстом. Используйте это только в тестовой сети.

Для сертификата от вашего собственного центра сертификации Docker в Linux читает сертификат центра из /etc/docker/certs.d/<хост>/ca.crt (с портом, если он не 443). Docker Desktop использует хранилище доверенных сертификатов системы.

Устранение неполадок ​

Docker выводит коды ошибок реестра строчными буквами и с пробелами, например denied или name invalid, а за ними — сообщение сервера. У каждой ошибки есть также ID запроса в detail.requestId. Передайте его администратору: по нему запрос находят в журнале сервера.

ОшибкаПричинаЧто делать
UNAUTHORIZED (401)Ключ отсутствует, неверен, истёк или отозванВойдите снова с действующим ключом
DENIED (403)Ключ не может писать или не видит репозиторий. Токен с областью read получает «Read-only personal access token».Используйте ключ с доступом на запись в этот репозиторий
DENIED (409)Репозиторий является зеркаломОтправляйте образы на основной сервер
DENIED (507)Достигнута квота репозитория или ёмкость установки. Незавершённые загрузки тоже учитываются.Освободите место или попросите увеличить квоту
NAME_INVALIDВ ссылке после репозитория нет части с именем образа или в ней есть прописные буквыИспользуйте <хост>/<репозиторий>/<образ>:<тег> строчными буквами
MANIFEST_UNKNOWNТега или дайджеста нет в этом образеПроверьте имя через tags/list
MANIFEST_BLOB_UNKNOWNМанифест ссылается на слой или платформенный манифест, которых нет в этом репозиторииОтправьте образ целиком ещё раз, чтобы клиент загрузил недостающие части
DIGEST_INVALIDБайты не совпадают с дайджестомПовторите push. Если ошибка повторяется, проверьте прокси-сервер.
TOOMANYREQUESTS (503 или 429)Слишком много одновременных передач этого ключа или сервер занятПодождите и повторите. Уменьшите число параллельных загрузок клиента, например "max-concurrent-uploads": 1 в конфигурации демона Docker, или попросите администратора поднять лимиты передач.
http: server gave HTTP response to HTTPS clientНа сервере нет HTTPSНастройте HTTPS или используйте insecure-registries для тестового сервера
x509: certificate signed by unknown authorityDocker не доверяет сертификатуУстановите сертификат центра сертификации, как описано выше
413 Request Entity Too LargeОбратный прокси-сервер ограничивает размер запросаЗадайте client_max_body_size 0 в nginx
Большой слой останавливается через 30 минутСрок загрузки одного запросаИспользуйте более быструю сеть или не кладите такие файлы в образы, а загружайте их через arkvoryctl

Arkvory · ProAnimaStudio