Skip to content

Proposal: Add support for OCI Image Layout #25779

@stevvooe

Description

@stevvooe

To validate support for the OCI Image Spec, we are going to add support for image layout to docker save and docker load.

The OCI Image Format is a content-addressable package roughly equivalent to the docker save/load format. It contains manifests with references to them.

When OCI images are loaded into docker, they become regular docker images. When they are exported again as OCI images, they will be serialized to the OCI Image Layout. The main additions here will be provisions to control which references become which images when imported to docker. Because the OCI Image Spec lacks naming, we include simple parameters for safely importing images into desired names.

This is best demonstrated by example.

The following would generate an image ubuntu:latest into an OCI Image Layout:

docker save --oci ubuntu > ubuntu-oci.tar.gz

This would create a ref "latest" pointing to the relevant OCI structures.

We can also support multiple tags:

docker save --oci ubuntu:15.10 ubuntu:16.04 > ubuntu-oci-multi.tar.gz

The above would create an image layout where the refs "15.10" and "16.04" would point to their respective manifests. This can also work with images from different repositories:

docker save --oci redis:3.2-alpine alpine > ubuntu-redis-oci.tar.gz

The above would create refs for latest and 3.2-alpine. However, the following would create a collision:

$ docker save --oci redis alpine
error: unable to include unique references in oci image

In this case, both redis and alpine have a latest, so we would have to map them. We introduce the --ref flag to handle these cases:

$ docker save --oci --ref redis=redis-latest --ref alpine=alpine-latest redis alpine > ubuntu-redis-refs-oci.tar.gz

At this point, it's important to note that mapping tags to references is merely a convention. The user can then use the --ref flag to map from the unconstrained ref space into the docker image namespace.

Let's introduce our first docker load, using the tars generated above:

docker load --oci --name ubuntu < ubuntu-oci.tar.gz

By default, this command will import the provide OCI image layout, into an image named ubuntu, translating all refs directly into tags. The same command from above can be used with the ubuntu-oci-multi.tar.gz:

docker save --oci --name ubuntu < ubuntu-oci-multi.tar.gz

Because ubuntu-oci-multi.tar.gz has refs "15.10" and "16.04", those tags are created in docker.

Let's move to the multi-image example:

$ docker load --oci --ref redis=redis-latest --ref alpine=alpine-latest < ubuntu-redis-refs-oci.tar.gz

Because we had multiple images, we have to tell docker how to correctly import each image based on the refs in the image layout file. First thing to note is the structure of the --ref command. It is always --ref <image>=<ref>, whether using it with docker save or docker load. For example, the above is really equivalent to --ref redis:latest=redis-latest. The other thing to note is the rough equivalence of the --name command and --ref command. The --name command is the same as listing all the refs in an image layout creating a --ref <image>:<ref>=<ref> where <image> is the argument to --name.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/distributionImage Distributionkind/featureFunctionality or other elements that the project doesn't currently have. Features are new and shiny

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions