Skip to content

Instantly share code, notes, and snippets.

@estesp
Created January 20, 2016 20:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save estesp/e8128058e02526d95acf to your computer and use it in GitHub Desktop.
Save estesp/e8128058e02526d95acf to your computer and use it in GitHub Desktop.
Distribution: Manifest List: User Interactions

Background

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.

Create

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.

Update

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

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.

@harche
Copy link

harche commented Feb 10, 2016

Syntax error in YAML file above. It should look like this,

--- 
image: myrepo/myimage
manifests: 
  - 
    image: myrepo/myimage_ppc64le
    platform: 
      architecture: ppc64
      os: Linux
      variant: ppc64le
  - 
    image: myrepo/myimage_amd64
    platform: 
      architecture: x86_64
      features: 
        - sse
      os: Linux

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment