15

According to https://docs.docker.com/registry/spec/api/ I can call /v2/<name>/tags/list to get a list of the tags for a given image. It works fine, e.g.:

{"name"=>"avi/test", "tags"=>["latest"]}

However, I would like the digest for each tag. Yes, the "digest" is actually the hash of the manifest (at least as I best understood it from the API; not 100% clear). However, I would like a way of knowing what a unique identifier for "latest" (and every other tag) is.

Use case: I might have someone tag a version as latest, and want to check if it is up to date:

docker push avi/test:2.6
docker tag avi/test:2.6 avi/test:latest
docker push avi/test:latest
# build 2.7
docker push avi/test:2.7
# oops! Forgot to tag latest to 2.7

In the above case, if I can check not just the tags - which will give me "2.6", "2.7", "latest" - but also the digest (at least of the manifest), I can find what various tags point to, audit, etc.

2 Answers 2

21

AFAIK, there isn't a digest API. However, according to the v2 API spec you can do a HEAD or GET request against /v2/<name>/manifests/<reference>. The response will include a Docker-Content-Digest header containing the digest of the specified manifest (e.g. latest).

Sign up to request clarification or add additional context in comments.

6 Comments

Ohhh, I missed that in the spec. So if I do HEAD /v2/avi/test/manifests/latest or HEAD /v2/avi/test/manifests/2.7 then the header for Docker-Content-Digest should be unique that I can compare versions?
Yes, the Docker-Content-Digest header should give you what you need.
when I'm using HEAD registry.hub.docker.com/v2/alpine/manifests/latest I'm getting 404, any idea?
I'm able to get a Docker-Content-Digest from this endpoint, but it's not the digest of the image, so I think this answer no longer applies. I've posted a follow-up question stackoverflow.com/q/39375421/1220269
The question @NathanielWaisbrot linked gives the correct answer. The short version is add an Accept: application/vnd.docker.distribution.manifest.v2+json header to the request and then Docker-Content-Digest is the correct digest.
|
2

It's been 8 years since this question was asked and answered and the Docker-Content-Digest header is now listed as legacy header in the OCI distribution spec. It is now an optional header and should not be depended upon according to the specs.

While I haven't encountered issues with it yet, the Docker-Content-Digest header no longer seems future-proof. However, you can also compute the digest yourself - it is simply the sha256 hexcode of the manifest. Which on Linux you can do as follows:

curl -H "Accept: application/vnd.docker.distribution.manifest.v2+json" https://<repo>/v2/<image>/manifests/<tag> | sha256sum

If you don't have the sha256 tool, here is an alternative example how you can manually compute it in Python

import json
import hashlib
import requests

headers = {'Accept': 'application/vnd.docker.distribution.manifest.v2+json'}
response = requests.get("https://<repo>/v2/<image>/manifests/<tag>", headers=headers)
serialized_manifest = json.dumps(
  response.json(), 
  indent=3    # weird but this spacing is required to get the right hash
).encode('utf-8')
digest = hashlib.sha256(serialized_manifest).hexdigest()

Depending on the Docker repository you're pulling from, you may need to add authentication headers.


EDIT: For any python developers that stumble across this, you can also get the digest in Python by using this function from the Docker SDK:

import docker
client = docker.from_env()
distr_info = client.api.inspect_distribution("my_image")
print(distr_info["Descriptor"]["digest"])

This is nicer if you're using Python. I'm also leaving the example above to help people trying to do this in other languages.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.