Created
April 30, 2020 15:53
-
-
Save tsprlng/5a1f1ab86e2e10a4ac504b20256ffb81 to your computer and use it in GitHub Desktop.
Get docker image hash from tag name for lockfile purposes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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