diff --git a/image/docker/schema2/manifest.py b/image/docker/schema2/manifest.py index ba7e3e84c..b30ea6535 100644 --- a/image/docker/schema2/manifest.py +++ b/image/docker/schema2/manifest.py @@ -128,6 +128,7 @@ class DockerSchema2Manifest(ManifestInterface): def __init__(self, manifest_bytes): self._layers = None self._payload = manifest_bytes + self._cached_built_config = None try: self._parsed = json.loads(manifest_bytes) @@ -212,11 +213,11 @@ class DockerSchema2Manifest(ManifestInterface): def child_manifests(self, content_retriever): return None - def _manifest_image_layers(self, content_retriever, schema2_config=None): + def _manifest_image_layers(self, content_retriever): assert not self.has_remote_layer # Retrieve the configuration for the manifest. - config = schema2_config or self._get_built_config(content_retriever) + config = self._get_built_config(content_retriever) history = list(config.history) if len(history) < len(self.layers): raise MalformedSchema2Manifest('Found less history than layer blobs') @@ -236,7 +237,7 @@ class DockerSchema2Manifest(ManifestInterface): compressed_size = EMPTY_LAYER_SIZE if blob_layer is None else blob_layer.compressed_size # Create a new synthesized V1 ID for the history layer by hashing its content and - # the blob associated withn it. + # the blob associated with it. digest_history.update(json.dumps(history_entry.raw_entry)) digest_history.update("|") digest_history.update(str(history_index)) @@ -307,7 +308,8 @@ class DockerSchema2Manifest(ManifestInterface): """ assert not self.has_remote_layer schema2_config = self._get_built_config(content_retriever) - layers = list(self._manifest_image_layers(content_retriever, schema2_config)) + layers = list(self._manifest_image_layers(content_retriever)) + for index, layer in enumerate(reversed(layers)): # Schema 1 layers are in reverse order v1_compatibility = schema2_config.build_v1_compatibility(layer.history, layer.v1_id, @@ -319,6 +321,9 @@ class DockerSchema2Manifest(ManifestInterface): return v1_builder def _get_built_config(self, content_retriever): + if self._cached_built_config: + return self._cached_built_config + config_bytes = content_retriever.get_blob_bytes_with_digest(self.config.digest) if config_bytes is None: raise MalformedSchema2Manifest('Could not load config blob for manifest') @@ -327,7 +332,8 @@ class DockerSchema2Manifest(ManifestInterface): raise MalformedSchema2Manifest('Size of config does not match that retrieved: %s vs %s', len(config_bytes), self.config.size) - return DockerSchema2Config(config_bytes) + self._cached_built_config = DockerSchema2Config(config_bytes) + return self._cached_built_config def _generate_layers(self): for index, layer in enumerate(self._parsed[DOCKER_SCHEMA2_MANIFEST_LAYERS_KEY]):