Как я могу использовать API реестра Docker для получения информации о контейнере? Получение НЕСАНКЦИОНИРОВАННО
Некоторое время назад я наткнулся на статью под названием " Проверка образов докеров", не тянув их, чтобы вникнуть в суть специфических вызовов API, необходимых для выполнения docker inspect
с остальными звонками. Однако мне интересно, возможно, что-то изменилось с API реестра Docker с момента написания этой статьи.
В статье рассказывается, что вам нужно сделать три вызова REST, чтобы получить информацию о контейнере. В случае общедоступного реестра Docker они выглядят следующим образом:
GET-запрос к auth.docker.io для получения токена
curl "https://auth.docker.io/token?scope=repository:<image>:pull&service=registry.docker.io"
В этом случае
image
может быть что-то вродеnginx
или жеdocker
- в основном, какое бы изображение вы ни искали. Этот вызов REST возвращает токен для использования в последующих запросах.GET-запрос для получения списков манифестов
curl -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -H "Authorization: Bearer <token-from-step-1>" "https://registry-1.docker.io/v2/<image>/manifests/<tag>"
Вот
image
такой же, как в шаге 1, иtag
может быть что-то вродеlatest
, Этот вызов возвращает некоторый JSON; ключ в том, что нам нужно извлечь значение в.config.digest
, Это строка дайджеста, которую мы используем в последнем запросе.Наконец GET-запрос для получения конфигурации контейнера, используя дайджест, полученный на шаге 2
curl -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -H "Authorization: Bearer <token-from-step-1>" "https://registry-1.docker.io/v2/<image>/blobs/<digest-from-step-2>"
Это возвращает некоторый JSON, и поле, о котором я забочусь,
.config
Я смог успешно проверить это в частном реестре Docker, хотя там мне пришлось сделать что-то другое для аутентификации. Однако у меня возникает противоположная проблема, когда я пытаюсь следовать руководству (которое я обрисовал в общих чертах в этих шагах выше) для общедоступного реестра Docker: шаг 1 дает мне токен, но этот токен бесполезен. Всякий раз, когда я пытаюсь использовать это, в Шагах 2 или 3, я получаю это обратно:
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"repository","Class":"","Name":"docker","Action":"pull"}]}]}
Любые идеи о том, как заставить это работать?
2 ответа
Используя следующие шаги вы можете получить конфигурацию любого общедоступного контейнера-образа.
Получите соответствующий токен для изображения. Обратите внимание, что вы должны указать полное имя изображения (официальные изображения используют
library
хранилище). Таким образом, изображение NGINX должно упоминаться как:library/nginx
,curl \ --silent \ "https://auth.docker.io/token?scope=repository:library/nginx:pull&service=registry.docker.io" \ | jq -r '.token'
Для краткости токен сокращен: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXV...
Получите дайджест изображения из манифеста. Для этого запроса также необходимо указать допустимый тег (в этом примере используется
latest
тег).curl \ --silent \ --header "Accept: application/vnd.docker.distribution.manifest.v2+json" \ --header "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXV..." \ "https://registry-1.docker.io/v2/library/nginx/manifests/latest" \ | jq -r '.config.digest'
sha256: 2bcb04bdb83f7c5dc30f0edaca1609a716bda1c7d2244d4f5fbbdfef33da366c
Наконец, получите конфигурацию контейнера, используя следующий запрос. В URL должен быть указан дайджест из второго шага.
curl \ --silent \ --location \ --header "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXV..." \ "https://registry-1.docker.io/v2/library/nginx/blobs/sha256:2bcb04bdb83f7c5dc30f0edaca1609a716bda1c7d2244d4f5fbbdfef33da366c" \ | jq -r '.container_config'
Вывод сокращен для краткости:
{ "Hostname": "6c02a05b3d09", "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "NGINX_VERSION=1.15.10-1~stretch", "NJS_VERSION=1.15.10.0.3.0-1~stretch" ], "Labels": { "maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>" }, "StopSignal": "SIGTERM" }
В статье говорится, что вам нужно сделать три вызова REST, чтобы получить информацию о контейнере.
об образе
Наконец, запрос GET для получения конфигурации контейнера.
конфигурация изображения
Скрипт, отображающий конфигурацию образа. Он работает с частными реестрами и Docker Hub. Для базовых регистров аутентификации вам необходимо указать второй аргумент (user:pass
).
#!/usr/bin/env bash
set -eu
image=$1
creds=${2-}
# https://github.com/moby/moby/blob/v20.10.18/vendor/github.com/docker/distribution/reference/normalize.go#L29-L57
# https://github.com/moby/moby/blob/v20.10.18/vendor/github.com/docker/distribution/reference/normalize.go#L88-L105
registry=${image%%/*}
if [ "$registry" = "$image" ] \
|| { [ "`expr index "$registry" .:`" = 0 ] && [ "$registry" != localhost ]; }; then
registry=docker.io
else
image=${image#*/}
fi
if [ "$registry" = docker.io ] && [ "`expr index "$image" /`" = 0 ]; then
image=library/$image
fi
if [ "`expr index "$image" :`" = 0 ]; then
tag=latest
else
tag=${image#*:}
image=${image%:*}
fi
if [ "$registry" = docker.io ]; then
registry=https://registry-1.docker.io
elif ! [[ "$registry" =~ ^localhost(:[0-9]+)$ ]]; then
registry=https://$registry
fi
r=`curl -sS "$registry/v2/" \
-o /dev/null \
-w '%{http_code}:%header{www-authenticate}'`
http_code=`echo "$r" | cut -d: -f1`
curl_args=(-sS -H 'Accept: application/vnd.docker.distribution.manifest.v2+json')
if [ "$http_code" = 401 ]; then
if [ "$registry" = https://registry-1.docker.io ]; then
header_www_authenticate=`echo "$r" | cut -d: -f2-`
header_www_authenticate=`echo "$header_www_authenticate" | sed -E 's/^Bearer +//'`
split_into_lines() {
sed -Ee :1 -e 's/^(([^",]|"([^"]|\")*")*),/\1\n/; t1'
}
header_www_authenticate=`echo "$header_www_authenticate" | split_into_lines`
extract_value() {
sed -E 's/^[^=]+="(([^"]|\")*)"$/\1/; s/\\(.)/\1/g'
}
realm=$(echo "$header_www_authenticate" | grep '^realm=' | extract_value)
service=$(echo "$header_www_authenticate" | grep '^service=' | extract_value)
scope=repository:$image:pull
token=`curl -sS "$realm?service=$service&scope=$scope" | jq -r .token`
curl_args+=(-H "Authorization: Bearer $token")
else
curl_args+=(-u "$creds")
fi
fi
manifest=`curl "${curl_args[@]}" "$registry/v2/$image/manifests/$tag"`
config_digest=`echo "$manifest" | jq -r .config.digest`
curl "${curl_args[@]}" -L "$registry/v2/$image/blobs/$config_digest" | jq -C
Использование:
$ ./image-config.sh ruby
$ ./image-config.sh library/ruby # same as the one above
$ ./image-config.sh docker.io/library/ruby # same as the previous two
$ ./image-config.sh docker.io/library/ruby:3.0.4
$ ./image-config.sh myregistry.com/hello-world testuser:testpassword
$ ./image-config.sh localhost:5000/hello-world
Пара замечаний по использованию API:
- Реестр представляет собой набор репозиториев. Подумайте о Гитхабе. Обычно имена репозиториев имеют форму
user/name
(напримерnginxproxy/nginx-proxy
). А вот с официальными репозиториями (которые все на самом деле начинаются сlibrary/
) первый сегмент может быть опущен (library/ruby
->ruby
). Также может быть только один сегмент (например, в частных реестрах), и иногда только первая часть называется репозиторием ( пример ). Или второй. - Репозиторий — это набор изображений. Некоторые из них помечены. Изображения без тегов обычно появляются, когда вы отправляете новую версию изображения с тем же тегом.
- Старая, но, может быть, несколько актуальная актуальная статья (по крайней мере, начало).
- URL-адрес реестра Docker Hub см. в этом ответе .
- Не ожидайте, что все в спецификации будет работать. Например, Docker Hub не реализует
/v2/_catalog
маршрут.