def multi_image_tarball(tag_to_image, tar, tag_to_v1_image=None): """Produce a "docker save" compatible tarball from the DockerImages. Args: tag_to_image: A dictionary of tags to the images they label. tar: the open tarfile into which we are writing the image tarball. tag_to_v1_image: A dictionary of tags to the v1 form of the images they label. If this isn't provided, the image is simply converted. """ def add_file(filename, contents): info = tarfile.TarInfo(filename) info.size = len(contents) tar.addfile(tarinfo=info, fileobj=io.BytesIO(contents)) tag_to_v1_image = tag_to_v1_image or {} # The manifest.json file contains a list of the images to load # and how to tag them. Each entry consists of three fields: # - Config: the name of the image's config_file() within the # saved tarball. # - Layers: the list of filenames for the blobs constituting # this image. The order is the reverse of the v1 # ancestry ordering. # - RepoTags: the list of tags to apply to this image once it # is loaded. manifests = [] for (tag, image) in six.iteritems(tag_to_image): # The config file is stored in a blob file named with its digest. digest = hashlib.sha256(image.config_file()).hexdigest() add_file(digest + '.json', image.config_file()) cfg = json.loads(image.config_file()) diffs = set(cfg.get('rootfs', {}).get('diff_ids', [])) v1_img = tag_to_v1_image.get(tag) if not v1_img: v2_img = v2_compat.V2FromV22(image) v1_img = v1_compat.V1FromV2(v2_img) tag_to_v1_image[tag] = v1_img # Add the manifests entry for this image. manifests.append({ 'Config': digest + '.json', 'Layers': [ layer_id + '/layer.tar' # We don't just exclude the empty tar because we leave its diff_id # in the set when coming through v2_compat.V22FromV2 for layer_id in reversed(v1_img.ancestry(v1_img.top())) if _diff_id(v1_img, layer_id) in diffs ], 'RepoTags': [str(tag)] }) # v2.2 tarballs are a superset of v1 tarballs, so delegate # to v1 to save itself. v1_save.multi_image_tarball(tag_to_v1_image, tar) add_file('manifest.json', json.dumps(manifests, sort_keys=True))
def main(): args = parser.parse_args() with docker_image.FromTarball(args.tarball) as v2_2_img: with open(args.output_id, 'w') as f: f.write(hashlib.sha256(v2_2_img.config_file()).hexdigest()) with v2_compat.V2FromV22(v2_2_img) as v2_img: with v1_compat.V1FromV2(v2_img) as v1_img: with open(args.output_name, 'w') as f: f.write(v1_img.top())
def main(): args = parser.parse_args() creds = docker_creds.Anonymous() transport = transport_pool.Http(httplib2.Http, size=8) name = docker_name.Tag(args.name) with tarfile.open(name=args.tarball, mode='w') as tar: with v2_2_image.FromRegistry(name, creds, transport) as v2_2_img: if v2_2_img.exists(): with v2_compat.V2FromV22(v2_2_img) as v2_img: with v1_compat.V1FromV2(v2_img) as v1_img: v1_image.save(name, v1_img, tar) return with v2_image.FromRegistry(name, creds, transport) as v2_img: with v1_compat.V1FromV2(v2_img) as v1_img: v1_image.save(name, v1_img, tar) return