Как отправить изображение в реестр Docker с помощью API реестра Docker v2

Я пишу обертку api реестра Docker для извлечения изображений из одного частного реестра и отправки их в другой.

На основании документации сначала мне нужно вытащить манифест и слои для image:tag, После создания изображения я успешно загрузил все слои для определенного image:tag и манифест.

После нажатия на изображение я выполнил следующие действия:

  1. POST /v2/<name>/blobs/uploads/ (чтобы получить UUID т.е. Location заголовок)
  2. HEAD /v2/<name>/blobs/<digest> (проверьте, существует ли он уже в реестре)
  3. PUT /v2/<name>/blobs/uploads/<uuid>?digest=<digest> (Monolithic Upload)

Что мне не понятно, так это следующее:

  1. Это uuid уникален для каждого отдельного слоя, который я нажимаю, или используется повторно для всех слоев (например, нужно ли мне запускать новый POST для каждого слоя и получать новый uuid прежде чем я попытаюсь загрузить его?).
  2. В разделе " Завершенная загрузка " указано

Чтобы загрузка считалась завершенной, клиент должен отправить запрос PUT на конечную точку загрузки с параметром дайджеста.

Однако, как уже упоминалось, я использую монолитную загрузку, которая использует PUT и будет такой же запрос, как показано в разделе "Завершенная загрузка". Таким образом, выполняя монолитную загрузку, я также одновременно завершаю загрузку?

проблема

  1. Когда я прохожу все вышеописанные шаги, я получаю BLOB_UNKNOWN ошибка при загрузке дайджеста, например

    { "errors:" [{ "code": "BLOB_UNKNOWN", "message": "blob неизвестно реестру", "detail": { "digest": } }, ... ] }

Согласно документации эта ошибка возникает при нажатии манифеста и один из слоев в манифесте неизвестны:

Если один или несколько слоев неизвестны реестру, возвращаются ошибки BLOB_UNKNOWN. Поле подробного ответа об ошибке будет иметь поле дайджеста, идентифицирующее отсутствующий большой двоичный объект. Ошибка возвращается для каждого неизвестного большого двоичного объекта. Формат ответа следующий:

Что меня смущает в этом

  1. Я выдвигаю дайджест (он же слой), а не манифест, так почему эта ошибка возвращается?
  2. Я ожидаю, что BLOB-объект будет неизвестен, потому что я помещаю новое изображение в реестр

На данный момент я собираюсь использовать докер-клиент, но я не нашел в Интернете никаких примеров обёрток, чтобы посмотреть, как это происходит. Предположительно, мне не хватает какой-то логики или недоразумений в документах, но я не уверен, где я ошибаюсь?

0 ответов

Вау, приятно осознавать, что я не единственный, кто потерял в пустоте API V2...

Я реализую аналогичную библиотеку и столкнулся с той же проблемой. Насколько я понимаю в документации, есть две монолитные загрузки: один обменPOST вариант (упомянутый в нижней части документации), и два обмена POST + PUT вариант (упомянутый в верхней части документации).

Мне не удалось заставить работать только метод POST. В моем случае я использовал его для загрузки манифеста изображения после больших двоичных объектов слоя и перед манифестом реестра. Хотя POST выглядит успешным и возвращает 202, журнал отладки в реестре показывает, что он никогда не реплицируется из промежуточного местоположения в хранилище данных (как это происходит после фрагментированных загрузок). Последующая попытка загрузить манифест затем завершается ошибкой с 400, и ведение журнала отладки "blob unknown to registry".

Однако мне удалось обойти эту проблему с помощью метода POST+PUT.

Ключевыми разделами в документации для меня были:

Хотя формат URI (/v2//blobs/uploads/) для заголовка Location указан, клиенты должны рассматривать его как непрозрачный URL-адрес и никогда не должны пытаться его собрать.

а также

Монолитная загрузка - это просто загрузка фрагментов с одним фрагментом...

Следуя этим двум инструкциям, я создал новый заголовок Location (и UUID) с помощью POST, добавил значение дайджеста и завершил загрузку, поместив BLOB-объект в измененное местоположение.

Боковое примечание: глядя на журналы отладки реестра, интерфейс командной строки докера проверяет наличие больших двоичных объектов перед началом новой загрузки (а также после завершения загрузки - при условии двойной проверки кода состояния).

Обновление: обнаружил, что снова работаю над этим, и решил, что сообщу вам, что я нашел...

Реестр поддерживает обработку тела ответа только во время операций PATCH и PUT; тоcopyFullPayloadhelper не вызывается для POST. Кроме того, все загрузки, по-видимому, обрабатываются как монолитные загрузки (в том смысле, что они передают большой двоичный объект из одного тела запроса) как обработкаContent-Rangeзаголовок, похоже, не реализован.

Боковое примечание: я провел этот анализ в рамках увеличения тестового покрытия V2 API во время капитального ремонта; вот рабочий пример метода POST+PUT. В общем, я обнаружил, что официальная документация не синхронизирована с текущей реализацией в отношении заголовков и кодов состояния. Я тестировал это в локальном реестре V2 и DockerHub, но не на других реестрах, таких как DTR, quay или MCR.

Другие вопросы по тегам