The manifest list type was introduced in the latest Docker distribution project's manifest schema (https://github.com/docker/distribution/blob/master/docs/spec/manifest-v2-2.md) and allows for multi-architecture and/or multi-OS blob storage underneath the same named tag.
The current Docker engine (1.10) and Docker Registry projects can now interact with the manifest list type via the registry API and updated manifest handler implementation, but currently there is no support for user interaction to create, update, or delete these manifest list objects in the registry.
The following user flows suggest the basic interactions that will be necessary and propose a general design as a starting point for discussions on how this capability will be added to the Docker engine/client tools.
To create a manifest list (a.k.a "fat manifest") the various existing references that will be made within the list must already exist in the registry. For the multi-architecture use case, we could expect that a user will have built the various architecture-supported images on a build farm and, after successful build/CI cycles, have pushed these images using standard Docker tools to a registry.
For example, I have a Dockerfile
which can be built on 3 platforms: amd64, ppc64le, and arm. After building each on their respective hosts, I can push these 3 images (from these separate host machines) as myrepo/myimage_<arch>, with a self-assigned architecture tag to keep them separate.
$ docker push myrepo/myimage_amd64:latest
$ docker push myrepo/myimage_ppc64le:latest
$ docker push myrepo/myimage_arm7h:latest
The next step would be to create a tool which can assemble these three manifest references into a manifest list entry in the registry. I assume there will likely be a debate as to whether this can be rolled into docker push
behavior or need to be a separate tool, but for example's sake we will call it manifest.
Because the amount of information able to be stored per entry (specifically, the platform
object shown in this manifestList example) it seems cumbersome to believe that command line flags would be suitable for representing the information passed to this manifest tool. We are proposing the following YAML format as an input for both the create and update steps:
image : myrepo/myimage
manifests :
- image : myrepo/myimage_ppc64le
platform :
"architecture": "ppc64"
"os" : "Linux"
"variant": "ppc64le"
- image : myrepo/myimage_amd64
platform :
"architecture": "x86_64"
"os" : "Linux"
"features" :
- "sse"
This YAML provides the references (in the manifests
section) to all images which will be combined into the manifest list, and then provides the platform detail for each, and finally, provides the overall name/tag under which this combined manifest list will be referenced. In this case, once the create step is complete, a docker pull myrepo/myimage
on any of the supported x86_64, ppc64le, or arm7h Linux architectures should pull the correct corresponding manifest (and therefore image blob layers) matching that daemon instance's architecture details.
To be specific, providing the above YAML file as a parameter we would have a command like:
manifest create --list myimage.yaml
As the tool parses the YAML, it will perform the appropriate digest lookups for the images, and use that information to create a manifest list object which can then be sent to the registry API and "pushed" as a new digest, referenced by the image name provided in the YAML. We assume Notary/signing will occur in the same flow here as it would with a single manifest push.
We believe update is a special form of create. Given multiple dependent images are involved, the image author/creator would first need to update the architecture or OS-dependent images in the target registry.
Once the image author has made the appropriate updates (e.g. a security fix) across all dependent images, the same YAML input can be provided to a manifest update
command such that the digests are looked up (finding the updated images that are now referenced by the names/tags in the YAML), and a new manifest list object is created. The old manifest list entry should be removed, and the new manifest list object "pushed" to the registry, effectively replacing the prior version, such that subsequent pulls on that name:tag will retrieve the updated dependent content.
Q: Are there any issues about atomicity with update? How does this work today with single manifest objects on update?
Delete should be straightforward. Although, it isn't clear that we need an end user exposed delete operation. The registry itself supports delete through the API, but this is not exposed to the Docker end user today (right?). However, it would be fairly simple to offer a manifest delete [REPO/]name:[TAG]
which removes the manifest list, but has no impact on the dependent images.
Syntax error in YAML file above. It should look like this,