Я пишу оболочку API-интерфейса реестра докеров, чтобы извлекать изображения из одного частного реестра и передавать их в другой.
Основываясь на документации, сначала мне нужно получить манифест и слои для image:tag . После загрузки изображения я успешно загрузил все слои для конкретного image:tag и манифеста.
После отправки изображения я выполнил следующие шаги:
POST /v2/<name>/blobs/uploads/ (чтобы получить UUID, т.е. заголовок Location)
HEAD /v2/<name>/blobs/<digest> (проверьте, существует ли он уже в реестре)
PUT /v2/<name>/blobs/uploads/<uuid>?digest=<digest> (Monolithic Upload )
Что мне непонятно, так это следующее:
- Является ли
UUID уникальным для каждого отдельного слоя, который я отправляю, или он повторно используется для всех слоев (например, нужно ли мне запускать новый POST для каждого слоя, чтобы получить новый UUID, прежде чем я попытаюсь загрузить его?).
- Раздел Завершенная загрузка указывает
Чтобы загрузка считалась завершенной, клиент должен отправить запрос PUT на конечную точку загрузки с параметром дайджеста.
Однако, как уже упоминалось, я использую монолитную загрузку, которая использует a PUT и будет тем же запросом, что и в разделе "Завершенная загрузка". Таким образом, выполняя монолитную загрузку, я одновременно завершаю загрузку?
Проблема
Когда я выполняю все вышеперечисленные шаги, я получаю ошибку BLOB_UNKNOWN при загрузке дайджеста, например.
{ "ошибки:" [{ "код": "BLOB_UNKNOWN", "сообщение": "большой двоичный объект неизвестен реестру", "подробности": { "дайджест": } }, ... ] }
Согласно документам, эта ошибка возникает при отправке манифеста, и один из слоев в манифесте неизвестен:
Если один или несколько слоев неизвестны реестру, возвращаются ошибки BLOB_UNKNOWN. Поле сведений ответа об ошибке будет иметь поле дайджеста, идентифицирующее отсутствующий большой двоичный объект. Ошибка возвращается для каждого неизвестного большого двоичного объекта. Формат ответа следующий:
Что меня смущает в этом
- Я отправляю дайджест (он же слой), а не манифест, так почему эта ошибка возвращается?
- Я ожидаю, что большой двоичный объект будет неизвестен, потому что я помещаю новый образ в реестр.
На данный момент я собираюсь использовать клиент докеров, но я не нашел в сети ни одного примера обертки, чтобы увидеть, как это делается. Предположительно, мне не хватает какой-то логики или я неправильно понимаю документы, но я не уверен, где я ошибаюсь?
Ответ 1 · рейтинг 4 · Richard Davis
Вау, приятно знать, что я не единственный, кто потерялся в пустоте с V2 API...
Я реализую аналогичную библиотеку и столкнулся с той же проблемой. Насколько я понимаю, в документации есть две загрузки Monolithic: вариант одной биржи POST (упомянутый в нижней части документации) и вариант двух бирж POST + PUT (упомянутый в верхней части документации). ).
Мне не удалось заставить работать только метод POST. В моем случае я использовал его для загрузки манифеста изображения после больших двоичных объектов слоя и перед манифестом реестра. Хотя POST выглядит успешным и возвращает 202, журнал отладки в реестре показывает, что он никогда не реплицировался из промежуточного местоположения в хранилище данных (как это происходит после загрузки по частям). Последующая попытка загрузить манифест завершается с ошибкой 400, а большой двоичный объект журнала отладки неизвестен реестру.
Однако мне удалось обойти эту проблему с помощью метода POST+PUT.
Ключевыми разделами в документах для меня были:
Хотя формат URI (/v2//blobs/uploads/) для заголовка Location указан, клиенты должны рассматривать его как непрозрачный URL-адрес и никогда не должны пытаться его собрать.
и
Монолитная загрузка - это просто загрузка по частям с одним куском...
Следуя этим двум инструкциям, я создал новый заголовок Location (и UUID) с помощью POST, добавил значение дайджеста и завершил загрузку, поместив большой двоичный объект в измененное местоположение.
Дополнительное примечание. Глядя на журналы отладки реестра, интерфейс командной строки Docker проверяет наличие больших двоичных объектов перед началом новой загрузки (а также после завершения загрузки - предполагается, что это двойная проверка кода состояния) .
Обновление: обнаружил, что снова работаю над этим, и решил сообщить вам о том, что я нашел...
Реестр поддерживает обработку тела ответа только во время PATCH и PUT; помощник copyFullPayload не вызывается для POST . Кроме того, все загрузки рассматриваются как монолитные загрузки (в том смысле, что они передают большой двоичный объект из одного тела запроса), поскольку обработка заголовка Content-Range делает не реализовано.
Боковое примечание: я провел этот анализ в рамках расширения тестового охвата V2 API во время капитального ремонта; здесь работает пример метода POST+PUT. В целом я обнаружил, что официальная документация не синхронизирована с текущей реализацией в отношении заголовков и кодов состояния. Я проверил это на локальном реестре V2 и DockerHub, но не на других реестрах, таких как DTR, quay или MCR.