How to get manifests using HTTP API v2?

2020-04-16 04:23发布

问题:

How to authenticate with the V2 API is useful and works.

REPO="https://hub.docker.com/v2"

I'm able to get tokens, list (my) repos and lists their images and tags.

curl --silent \
--header "Authorization: JWT ${TOKEN}" \
${REPO}/repositories/${USERNAME}/

curl --silent \
--header "Authorization: JWT ${TOKEN}" \
${REPO}/repositories/${USERNAME}/${IMAGE}/tags/

I'd like to 'GET MANIFEST' but I'm struggling to get this to work: https://docs.docker.com/registry/spec/api/#manifest:

curl --silent \
--header "Host: hub.docker.com" \
--header "Authorization: JWT ${TOKEN}" \
${REPO}/repositories/${USERNAME}/${IMAGE}/manifests/

curl --silent \
--header "Host: hub.docker.com" \
--header "Authorization: JWT ${TOKEN}" \
${REPO}/${USERNAME}/${IMAGE}/manifests/

curl --silent \
--header "Host: hub.docker.com" \
--header "Authorization: JWT ${TOKEN}" \
${REPO}/${USERNAME}/${IMAGE}/manifests/${TAG}

I've tried with|without the Host header. With various values for the Host header. But, I'm clearly missing something. I tried pattern-matching against the working endpoints but no joy:

curl --silent \
--header "Authorization: JWT ${TOKEN}" \
${REPO}/repositories/${USERNAME}/${IMAGE}/manifests/

Curiously, this page shows "GET TAGS" seemingly incorrectly as /v2/<name>/tags/list: https://docs.docker.com/registry/spec/api/#tags

Reviewed: https://stackoverflow.com/a/45605443/609290

Follow-up

I'm a Googler and have access to Google Container Registry (GCR).

REPO="https://gcr.io/v2/"

On a whim, I just tried 'GET MANIFEST' against GCR and the requests works:

curl --silent \
--request GET \
--user _token:$(gcloud auth print-access-token) \
${REPO}/${PROJECT}/${IMAGE}/manifests/${TAG}

回答1:

It's quite confusing with all the *.docker.com|io subdomains!
I found registry.hub.docker.com and index.docker.io the most reliable ones.

You can easily query the tags from there, but for the manifests you'll need to get a token for pulling first:


REGISTRY=https://index.docker.io/v2
#REGISTRY="https://registry.hub.docker.com/v2"
#REGISTRY="https://registry.docker.io/v2"
#REGISTRY="https://registry-1.docker.io/v2"
#REGISTRY="https://hub.docker.com/v2"

REPO=library
IMAGE=debian
# Could also be a repo digest
TAG=latest

# Query tags
curl "$REGISTRY/repositories/$REPO/$IMAGE/tags/"

# Query manifest
curl -iL "$REGISTRY/$REPO/$IMAGE/manifests/$TAG"
# HTTP/1.1 401 Unauthorized
# Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:library/debian:pull"

TOKEN=$(curl -sSL "https://auth.docker.io/token?service=registry.docker.io&scope=repository:$REPO/$IMAGE:pull" \
  | jq --raw-output .token)
curl -LH "Authorization: Bearer ${TOKEN}" "$REGISTRY/$REPO/$IMAGE/manifests/$TAG"

# Some repos seem to return V1 Schemas by default

REPO=nginxinc
IMAGE=nginx-unprivileged 
TAG=1.17.2

curl -LH "Authorization: Bearer $(curl -sSL "https://auth.docker.io/token?service=registry.docker.io&scope=repository:$REPO/$IMAGE:pull" | jq --raw-output .token)" \
 "$REGISTRY/$REPO/$IMAGE/manifests/$TAG"

# Solution: Set the Accept Header for V2

curl -LH "Authorization: Bearer $(curl -sSL "https://auth.docker.io/token?service=registry.docker.io&scope=repository:$REPO/$IMAGE:pull" | jq --raw-output .token)" \
  -H "Accept:application/vnd.docker.distribution.manifest.v2+json" \
 "$REGISTRY/$REPO/$IMAGE/manifests/$TAG"

See

  • this gist for another example and
  • this repo for a reusable script docker-image-size-curl.sh

Authorization with hub.docker.com works differently and you don't seem to get the manifests from there