Skip to content

Instantly share code, notes, and snippets.

@tsprlng
Created April 30, 2020 15:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tsprlng/5a1f1ab86e2e10a4ac504b20256ffb81 to your computer and use it in GitHub Desktop.
Save tsprlng/5a1f1ab86e2e10a4ac504b20256ffb81 to your computer and use it in GitHub Desktop.
Get docker image hash from tag name for lockfile purposes
#!/usr/bin/env python3
import base64
import json
import requests
from os import environ, path
try:
UserPass = environ['DOCKER_HUB_AUTH']
except:
with open(path.expanduser('~/.docker/config.json')) as cfg:
UserPass = base64.b64decode(list(json.loads(cfg.read())['auths'].values())[0]['auth']).decode('utf8')
def describeImageWithHash(imageRepoName, imageTag):
token = requests.get('https://auth.docker.io/token?service=registry.docker.io&scope=repository:{}:pull'.format(imageRepoName),
auth=tuple(UserPass.split(':'))
).json()['token']
manifest1 = requests.get('https://registry.hub.docker.com/v2/{}/manifests/{}'.format(imageRepoName, imageTag),
headers={
'Accept': 'application/vnd.docker.distribution.manifest.v1+prettyjws',
'Authorization': 'Bearer {}'.format(token),
}
)
if manifest1.status_code != 200:
raise ValueError("Got {} response for v1 manifest".format(manifest1.status_code))
manifest2 = requests.get('https://registry.hub.docker.com/v2/{}/manifests/{}'.format(imageRepoName, imageTag),
headers={
'Accept': 'application/vnd.docker.distribution.manifest.v2+json',
'Authorization': 'Bearer {}'.format(token),
}
)
if manifest2.status_code != 200:
raise ValueError("Got {} response for v2 manifest".format(manifest2.status_code))
# Make sure there wasn't a push between our two requests!
# Annoyingly there is no single hash in common between the two manifest versions, so the only thing in common is the set of layer checksums.
checkLayerSums1 = set(l['blobSum'] for l in manifest1.json()['fsLayers'] if l['blobSum'] != 'sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4')
checkLayerSums2 = set(l['digest'] for l in manifest2.json()['layers'] if l['digest'] != 'sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4')
assert len(checkLayerSums1) > 1
assert checkLayerSums1 == checkLayerSums2, "{} vs. {}".format(checkLayerSums1, checkLayerSums2)
return '{}@{}'.format(imageRepoName, manifest2.headers['Docker-Content-Digest'])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment