dockerapidocker-registrydockerhubdocker-api

How to make a HEAD request to Docker Hub API to get the manifest?


I need to reach manifests of a lot of images on Docker hub, but every GET request for getting manifest is counted as a pull, as a result, I am restricted by the rate limits of docker hub. Is there a way to get the manifest with a HEAD request instead of GET from the API?

Edit: From Docker registry API documentation :

GET /v2//manifests/: Fetch the manifest identified by name and reference where reference can be a tag or digest. A HEAD request can also be issued to this endpoint to obtain resource information without receiving all data.

So I assume we can get related information with an HEAD request.


Solution

  • A shell script to do that looks like:

    #!/bin/sh
    
    ref="${1:-library/ubuntu:latest}"
    sha="${ref#*@}"
    if [ "$sha" = "$ref" ]; then
      sha=""
    fi
    wosha="${ref%%@*}"
    repo="${wosha%:*}"
    tag="${wosha##*:}"
    if [ "$tag" = "$wosha" ]; then
      tag="latest"
    fi
    apio="application/vnd.oci.image.index.v1+json"
    apiol="application/vnd.oci.image.manifest.v1+json"
    apid="application/vnd.docker.distribution.manifest.v2+json"
    apidl="application/vnd.docker.distribution.manifest.list.v2+json"
    token=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:${repo}:pull" \
            | jq -r '.token')
    curl -H "Accept: ${apio}" -H "Accept: ${apiol}" -H "Accept: ${apid}" -H "Accept: ${apidl}" \
         -H "Authorization: Bearer $token" \
         -I -s "https://registry-1.docker.io/v2/${repo}/manifests/${sha:-$tag}" 
    

    Note that the head request only shows the headers, and the most useful one is docker-content-digest so you can get the digest for a specific tag:

    HTTP/1.1 200 OK
    content-length: 1416
    content-type: application/vnd.docker.distribution.manifest.list.v2+json
    docker-content-digest: sha256:20fa2d7bb4de7723f542be5923b06c4d704370f0390e4ae9e1c833c8785644c1
    docker-distribution-api-version: registry/2.0
    etag: "sha256:20fa2d7bb4de7723f542be5923b06c4d704370f0390e4ae9e1c833c8785644c1"
    date: Thu, 08 Sep 2022 17:45:42 GMT
    strict-transport-security: max-age=31536000
    ratelimit-limit: 100;w=21600
    ratelimit-remaining: 100;w=21600
    docker-ratelimit-source: 68.100.24.47
    

    If you want to do this for other registries, you'll need to adjust the authentication. Both go-containerregistry's crane and regclient's regctl tools have image digest commands that handle the authentication and return just the digest.