docs/spec: Proposal for new manifest format
This is a follow-on to PR #62, and it borrows much of the format from #993, but uses specific formats for the image manifest and manifest list (fat manifest) instead of a combined generic format. The intent of this proposed manifest format is to allow multi-arch, and allow for full content-addressability of images in the Docker engine. Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
This commit is contained in:
parent
67d3675d55
commit
2e3f4934a7
267
docs/spec/manifest-v2-2.md
Executable file
267
docs/spec/manifest-v2-2.md
Executable file
@ -0,0 +1,267 @@
|
||||
# Image Manifest Version 2, Schema 2
|
||||
|
||||
This document outlines the format of of the V2 image manifest, schema version 2.
|
||||
The original (and provisional) image manifest for V2 (schema 1), was introduced
|
||||
in the Docker daemon in the [v1.3.0
|
||||
release](https://github.com/docker/docker/commit/9f482a66ab37ec396ac61ed0c00d59122ac07453)
|
||||
and is specified in the [schema 1 manifest definition](./manifest-v2-1.md)
|
||||
|
||||
This second schema version has two primary goals. The first is to allow
|
||||
multi-architecture images, through a "fat manifest" which references image
|
||||
manifests for platform-specific versions of an image. The second is to
|
||||
move the Docker engine towards content-addressable images, by supporting
|
||||
an image model where the image's configuration can be hashed to generate
|
||||
an ID for the image.
|
||||
|
||||
# Media Types
|
||||
|
||||
The following media types are used by the manifest formats described here, and
|
||||
the resources they reference:
|
||||
|
||||
- `application/vnd.docker.distribution.manifest.v1+json`: schema1 (existing manifest format)
|
||||
- `application/vnd.docker.distribution.manifest.v2+json`: New image manifest format (schemaVersion = 2)
|
||||
- `application/vnd.docker.distribution.manifest.list.v2+json`: Manifest list, aka "fat manifest"
|
||||
- `application/vnd.docker.image.rootfs.diff.tar.gzip`: "Layer", as a gzipped tar
|
||||
- `application/vnd.docker.container.image.v1+json`: Container config JSON
|
||||
|
||||
## Manifest List
|
||||
|
||||
The manifest list is the "fat manifest" which points to specific image manifests
|
||||
for one or more platforms. Its use is optional, and relatively few images will
|
||||
use one of these manifests. A client will distinguish a manifest list from an
|
||||
image manifest based on the Content-Type returned in the HTTP response.
|
||||
|
||||
## *Manifest List* Field Descriptions
|
||||
|
||||
- **`schemaVersion`** *int*
|
||||
|
||||
This field specifies the image manifest schema version as an integer. This
|
||||
schema uses the version `2`.
|
||||
|
||||
- **`mediaType`** *string*
|
||||
|
||||
The MIME type of the manifest list. This should be set to
|
||||
`application/vnd.docker.distribution.manifest.list.v2+json`.
|
||||
|
||||
- **`manifests`** *array*
|
||||
|
||||
The manifests field contains a list of manifests for specific platforms.
|
||||
|
||||
Fields of a object in the manifests list are:
|
||||
|
||||
- **`mediaType`** *string*
|
||||
|
||||
The MIME type of the referenced object. This will generally be
|
||||
`application/vnd.docker.image.manifest.v2+json`, but it could also
|
||||
be `application/vnd.docker.image.manifest.v1+json` if the manifest
|
||||
list references a legacy schema-1 manifest.
|
||||
|
||||
- **`size`** *int*
|
||||
|
||||
The size in bytes of the object. This field exists so that a client
|
||||
will have an expected size for the content before validating. If the
|
||||
length of the retrieved content does not match the specified length,
|
||||
the content should not be trusted.
|
||||
|
||||
- **`digest`** *string*
|
||||
|
||||
The digest of the content, as defined by the
|
||||
[Registry V2 HTTP API Specificiation](https://docs.docker.com/registry/spec/api/#digest-parameter).
|
||||
|
||||
- **`platform`** *object*
|
||||
|
||||
The platform object describes the platform which the image in the
|
||||
manifest runs on.
|
||||
|
||||
- **`architecture`** *string*
|
||||
|
||||
The architecture field specifies the CPU architecture, for example
|
||||
`amd64` or `ppc64`.
|
||||
|
||||
- **`os`** *string*
|
||||
|
||||
The architecture field specifies the operating system, for example
|
||||
`linux` or `windows`.
|
||||
|
||||
- **`variant`** *string*
|
||||
|
||||
The optional variant field specifies a variant of the CPU, for
|
||||
example `ppc64le` to specify a little-endian version of a PowerPC
|
||||
CPU.
|
||||
|
||||
- **`features`** *array*
|
||||
|
||||
The optional features field specifies an array of strings, each
|
||||
listing a required CPU feature (for example `sse4` or `aes`).
|
||||
|
||||
## Example Manifest List
|
||||
|
||||
*Example showing a simple manifest list pointing to image manifests for two platforms:*
|
||||
```json
|
||||
{
|
||||
"schemaVersion": 2,
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
|
||||
"manifests": [
|
||||
{
|
||||
"mediaType": "application/vnd.docker.image.manifest.v2+json",
|
||||
"size": 7143,
|
||||
"digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f",
|
||||
"platform": {
|
||||
"architecture": "ppc64",
|
||||
"os": "linux",
|
||||
"variant": "ppc64le",
|
||||
}
|
||||
},
|
||||
{
|
||||
"mediaType": "application/vnd.docker.image.manifest.v2+json",
|
||||
"size": 7682,
|
||||
"digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270",
|
||||
"platform": {
|
||||
"architecture": "x86-64",
|
||||
"os": "linux",
|
||||
"features": [
|
||||
"sse4"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
# Image Manifest
|
||||
|
||||
The image manifest provides a configuration and a set of layers for a container
|
||||
image. It's the direct replacement for the schema-1 manifest.
|
||||
|
||||
## *Image Manifest* Field Descriptions
|
||||
|
||||
- **`schemaVersion`** *int*
|
||||
|
||||
This field specifies the image manifest schema version as an integer. This
|
||||
schema uses version `2`.
|
||||
|
||||
- **`mediaType`** *string*
|
||||
|
||||
The MIME type of the manifest. This should be set to
|
||||
`application/vnd.docker.distribution.manifest.v2+json`.
|
||||
|
||||
- **`config`** *object*
|
||||
|
||||
The config field references a configuration object for a container, by
|
||||
digest. This configuration item is a JSON blob that the runtime uses
|
||||
to set up the container. This new schema uses a tweaked version
|
||||
of this configuration to allow image content-addressability on the
|
||||
daemon side.
|
||||
|
||||
Fields of a config object are:
|
||||
|
||||
- **`mediaType`** *string*
|
||||
|
||||
The MIME type of the referenced object. This should generally be
|
||||
`application/vnd.docker.container.image.v1+json`.
|
||||
|
||||
- **`size`** *int*
|
||||
|
||||
The size in bytes of the object. This field exists so that a client
|
||||
will have an expected size for the content before validating. If the
|
||||
length of the retrieved content does not match the specified length,
|
||||
the content should not be trusted.
|
||||
|
||||
- **`digest`** *string*
|
||||
|
||||
The digest of the content, as defined by the
|
||||
[Registry V2 HTTP API Specificiation](https://docs.docker.com/registry/spec/api/#digest-parameter).
|
||||
|
||||
- **`layers`** *array*
|
||||
|
||||
The layer list is ordered starting from the base image (opposite order of schema1).
|
||||
|
||||
Fields of an item in the layers list are:
|
||||
|
||||
- **`mediaType`** *string*
|
||||
|
||||
The MIME type of the referenced object. This should
|
||||
generally be `application/vnd.docker.image.rootfs.diff.tar.gzip`.
|
||||
|
||||
- **`size`** *int*
|
||||
|
||||
The size in bytes of the object. This field exists so that a client
|
||||
will have an expected size for the content before validating. If the
|
||||
length of the retrieved content does not match the specified length,
|
||||
the content should not be trusted.
|
||||
|
||||
- **`digest`** *string*
|
||||
|
||||
The digest of the content, as defined by the
|
||||
[Registry V2 HTTP API Specificiation](https://docs.docker.com/registry/spec/api/#digest-parameter).
|
||||
|
||||
## Example Image Manifest
|
||||
|
||||
*Example showing an image manifest:*
|
||||
```json
|
||||
{
|
||||
"schemaVersion": 2,
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||
"config": {
|
||||
"mediaType": "application/vnd.docker.container.image.v1+json",
|
||||
"size": 7023,
|
||||
"digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7"
|
||||
},
|
||||
"layers": [
|
||||
{
|
||||
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||
"size": 32654,
|
||||
"digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f"
|
||||
},
|
||||
{
|
||||
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||
"size": 16724,
|
||||
"digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b"
|
||||
},
|
||||
{
|
||||
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||
"size": 73109,
|
||||
"digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736"
|
||||
}
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
# Backward compatibility
|
||||
|
||||
The registry will continue to accept uploads of manifests in both the old and
|
||||
new formats.
|
||||
|
||||
When pushing images, clients which support the new manifest format should first
|
||||
construct a manifest in the new format. If uploading this manifest fails,
|
||||
presumably because the registry only supports the old format, the client may
|
||||
fall back to uploading a manifest in the old format.
|
||||
|
||||
When pulling images, clients indicate support for this new version of the
|
||||
manifest format by sending the
|
||||
`application/vnd.docker.distribution.manifest.v2+json` and
|
||||
`application/vnd.docker.distribution.manifest.list.v2+json` media types in an
|
||||
`Accept` header when making a request to the `manifests` endpoint. Updated
|
||||
clients should check the `Content-Type` header to see whether the manifest
|
||||
returned from the endpoint is in the old format, or is an image manifest or
|
||||
manifest list in the new format.
|
||||
|
||||
If the manifest being requested uses the new format, and the appropriate media
|
||||
type is not present in an `Accept` header, the registry will assume that the
|
||||
client cannot handle the manifest as-is, and rewrite it on the fly into the old
|
||||
format. If the object that would otherwise be returned is a manifest list, the
|
||||
registry will look up the appropriate manifest for the x86-64 platform and
|
||||
linux OS, rewrite that manifest into the old format if necessary, and return
|
||||
the result to the client. If no suitable manifest is found in the manifest
|
||||
list, the registry will return a 404 error.
|
||||
|
||||
One of the challenges in rewriting manifests to the old format is that the old
|
||||
format involves an image configuration for each layer in the manifest, but the
|
||||
new format only provides one image configuration. To work around this, the
|
||||
registry will create synthetic image configurations for all layers except the
|
||||
top layer. These image configurations will not result in runnable images on
|
||||
their own, but only serve to fill in the parent chain in a compatible way.
|
||||
The IDs in these synthetic configurations will be derived from hashes of their
|
||||
respective blobs. The registry will create these configurations and their IDs
|
||||
using the same scheme as Docker 1.10 when it creates a legacy manifest to push
|
||||
to a registry which doesn't support the new format.
|
Loading…
Reference in New Issue
Block a user