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

Я пишу оболочку API-интерфейса реестра докеров, чтобы извлекать изображения из одного частного реестра и передавать их в другой.

Основываясь на документации, сначала мне нужно получить манифест и слои для 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 на конечную точку загрузки с параметром дайджеста.

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

Проблема

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

    { "ошибки:" [{ "код": "BLOB_UNKNOWN", "сообщение": "большой двоичный объект неизвестен реестру", "подробности": { "дайджест": } }, ... ] }

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

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

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

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

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


person mdo123    schedule 07.02.2019    source источник
comment
Немного поздно для вечеринки и ни в коем случае не решение: вы рассматривали возможность использования клиента докера (как вы сказали), но через прокси-сервер, который позволил бы вам проверять трафик? Поскольку клиент общается с реестром v2 в виде обычного текста по протоколу http, трафик может быть прочитан и понят человеком.   -  person Justin Tamblyn    schedule 30.05.2019
comment
Удалось ли вам добиться успеха? у меня такая же проблема   -  person Ayrton Werck    schedule 29.05.2020


Ответы (1)


Вау, приятно знать, что я не единственный, кто потерялся в пустоте с 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.

person Richard Davis    schedule 17.07.2019