Last active
June 9, 2021 17:39
-
-
Save tsaarni/a9a76530f35c301b794bea216cfd8748 to your computer and use it in GitHub Desktop.
Upload image to registry with uncompressed layers
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 os | |
import subprocess | |
import requests | |
import json | |
import gzip | |
import hashlib | |
SOURCE_IMAGE = 'docker://alpine:latest' | |
DEST_REGISTRY_URL = 'https://registry.192-168-1-130.nip.io:8443' | |
DEST_REPO_NAME = 'uncompressed-alpine' | |
DEST_REPO_TAG = 'latest' | |
BUF_SIZE = 100000 | |
# unzip compressed layer, | |
# return hash over unzipped data and uncompressed size | |
def uncompressed_layer_info(compressed_file): | |
with gzip.open(compressed_file, 'rb') as f: | |
buf = f.read(BUF_SIZE) | |
uncompressed_size = len(buf) | |
h = hashlib.sha256() | |
while len(buf) > 0: | |
h.update(buf) | |
buf = f.read(BUF_SIZE) | |
uncompressed_size = uncompressed_size + len(buf) | |
return 'sha256:' + h.hexdigest(), uncompressed_size | |
# upload blob to registry | |
def upload_blob(registry_url, repo, filehandle, digest): | |
# initiate upload | |
r = requests.post( | |
f'{registry_url}/v2/{repo}/blobs/uploads/', | |
verify=False) | |
upload_url = r.headers['Location'] | |
# upload file | |
requests.put( | |
upload_url, | |
headers={'Content-Type': 'application/octet-stream'}, | |
params={'digest': digest}, | |
data=filehandle, | |
verify=False) | |
# download image | |
subprocess.call(f'skopeo copy {SOURCE_IMAGE} dir:input', shell=True) | |
with open('input/manifest.json') as m: | |
manifest = json.load(m) | |
# upload uncompressed layers | |
for layer in manifest['layers']: | |
layer_filename = os.path.join('input', layer['digest'].split(':')[1]) | |
digest, size = uncompressed_layer_info(layer_filename) | |
with gzip.open(layer_filename) as f: | |
upload_blob(DEST_REGISTRY_URL, DEST_REPO_NAME, f, digest) | |
# update manifest with uncompressed layer info | |
layer['mediaType'] = 'application/vnd.docker.image.rootfs.diff.tar' | |
layer['digest'] = digest | |
layer['size'] = size | |
# upload image config | |
digest = manifest['config']['digest'] | |
config_filename = os.path.join('input', digest.split(':')[1]) | |
with open(config_filename) as f: | |
upload_blob(DEST_REGISTRY_URL, DEST_REPO_NAME, f, digest) | |
# upload manifest with uncompressed layer references | |
requests.put( | |
f'{DEST_REGISTRY_URL}/v2/{DEST_REPO_NAME}/manifests/{DEST_REPO_TAG}', | |
headers={'Content-Type': 'application/vnd.docker.distribution.manifest.v2+json'}, | |
json=manifest, | |
verify=False) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment