K8S 1.20 deprecates the difference between Docker and OCI image formats for Docker assessment

This article was last updated on: July 24, 2024 am

background

In early December 2020, Kubernetes announced in its latest Changelog that it would deprecate Docker as a container runtime after Kubernetes 1.20.

Deprecation of Docker may bring a series of changes, including but not limited to:

  • Container image build tools
  • Container CLI
  • Container image repository
  • Container runtime

The feature article “K8S 1.20 Deprecation Docker Assessment” will analyze the resulting changes and impacts from many aspects, and today we will introduce the change in image format.

Are Docker images still usable?

Yes, it can be used. The image produced by a newer version of Docker is not actually a Docker-specific image, but rather an OCI (Open Container Initiativemirroring. No matter what tool you use to build the image, any OCI-compliant image looks the same to Kubernetes. Both containerd and CRI-O are able to extract these images and run them. So you can still use Docker to build container images, and you can continue to use it on containerd and CRI-O.

So why was there an incompatibility between Docker images and Containerd images?

Here’s how: In K8S > 1.20, containerd was found ctr The following issues exist between the image uploaded to the image repository and the docker image of the same version

  1. Cannot be used by Docker
  2. Docker push cannot be overridden

The root cause is still the difference in image format. This is explained in detail below.

What is the difference between Docker and OCI image formats?

Currently, there are the following container image formats:

Docker V1 images

Critical warning

The Docker V1 format has long been deprecated and should not be used anymore!!!

📖 cite

  1. Version 1.8.3 adds a flag (--disable-legacy-registry=false) to prevent the docker daemon from pulling, pushing, and logging in to the v1 image registry. Although enabled by default, this indicates that the v1 protocol is deprecated.
  2. As of February 28, 2017, with the release of Docker v1.13, Docker Engine is no longer supported v1 protocol
  3. Starting with Docker 17.12,Support for V1 mirrored registries has been removedmoreover --disable-legacy-registry The flag is no longer used when the flag is set dockerd will not start.

Introduction to Docker V2 images

Docker V2 Image Manifestis Docker’s V2 version of the container image specification that allows multi-architecture mirroring and supports content-addressable images.

Starting February 28, 2017,Docker V2 image registry specificationReplaces the Docker V1 specification. The Docker V1 specification has been deprecated and Docker V1 images can no longer be used in Container Registry.

To support content-addressable mirroring and simplify tracking of mirrored layers, Docker V2 makes a series of changes to the Docker image format. The Docker V2 image manifest contains all the content addresses (“summaries”) of the mirrored layer, while Docker V1 images do not.

Docker Image Manifest V2 Schema 1

The following is a brief description of the format of the V2 Schema 1 image manifest. V2 Schema 1 is a temporary manifest that provides compatibility with the V1 Image format, which is the final format of the current Docker image format.

📓 remark

V2 Schema 1 is more complex than V2.2 (i.e. Docker Image Manifest V2 Schema 2) due to the need for backward compatibility with V1.

The image manifest describes the various components of a Docker image. The image manifest can be serialized to JSON format with the following media types:

Manifest Type Media Type
manifest “application/vnd.docker.distribution.manifest.v1+json”
signed manifest “application/vnd.docker.distribution.manifest.v1+prettyjws”

The manifest format is not detailed, but the following is illustrated with an example:

Example manifest format

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
{
"name": "hello-world",
"tag": "latest",
"architecture": "amd64",
"fsLayers": [
{
"blobSum": "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
},
{
"blobSum": "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
},
{
"blobSum": "sha256:cc8567d70002e957612902a8e985ea129d831ebe04057d88fb644857caa45d11"
},
{
"blobSum": "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
}
],
"history": [
{
"v1Compatibility": "{\"id\":\"e45a5af57b00862e5ef5782a9925979a02ba2b12dff832fd0991335f4a11e5c5\",\"parent\":\"31cbccb51277105ba3ae35ce33c22b69c9e3f1002e76e4c736a2e8ebff9d7b5d\",\"created\":\"2014-12-31T22:57:59.178729048Z\",\"container\":\"27b45f8fb11795b52e9605b686159729b0d9ca92f76d40fb4f05a62e19c46b4f\",\"container_config\":{\"Hostname\":\"8ce6509d66e2\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) CMD [/hello]\"],\"Image\":\"31cbccb51277105ba3ae35ce33c22b69c9e3f1002e76e4c736a2e8ebff9d7b5d\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"SecurityOpt\":null,\"Labels\":null},\"docker_version\":\"1.4.1\",\"config\":{\"Hostname\":\"8ce6509d66e2\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/hello\"],\"Image\":\"31cbccb51277105ba3ae35ce33c22b69c9e3f1002e76e4c736a2e8ebff9d7b5d\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"SecurityOpt\":null,\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"
},
{
"v1Compatibility": "{\"id\":\"e45a5af57b00862e5ef5782a9925979a02ba2b12dff832fd0991335f4a11e5c5\",\"parent\":\"31cbccb51277105ba3ae35ce33c22b69c9e3f1002e76e4c736a2e8ebff9d7b5d\",\"created\":\"2014-12-31T22:57:59.178729048Z\",\"container\":\"27b45f8fb11795b52e9605b686159729b0d9ca92f76d40fb4f05a62e19c46b4f\",\"container_config\":{\"Hostname\":\"8ce6509d66e2\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) CMD [/hello]\"],\"Image\":\"31cbccb51277105ba3ae35ce33c22b69c9e3f1002e76e4c736a2e8ebff9d7b5d\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"SecurityOpt\":null,\"Labels\":null},\"docker_version\":\"1.4.1\",\"config\":{\"Hostname\":\"8ce6509d66e2\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/hello\"],\"Image\":\"31cbccb51277105ba3ae35ce33c22b69c9e3f1002e76e4c736a2e8ebff9d7b5d\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"SecurityOpt\":null,\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"
},
],
"schemaVersion": 1,
"signatures": [
{
"header": {
"jwk": {
"crv": "P-256",
"kid": "OD6I:6DRK:JXEJ:KBM4:255X:NSAA:MUSF:E4VM:ZI6W:CUN2:L4Z6:LSF4",
"kty": "EC",
"x": "3gAwX48IQ5oaYQAYSxor6rYYc_6yjuLCjtQ9LUakg4A",
"y": "t72ge6kIA1XOjqjVoEOiPPAURltJFBMGDSQvEGVB010"
},
"alg": "ES256"
},
"signature": "XREm0L8WNn27Ga_iE_vRnTxVMhhYY0Zst_FfkKopg6gWSoTOZTuW4rK0fg_IqnKkEKlbD83tD46LKEGi5aIVFg",
"protected": "eyJmb3JtYXRMZW5ndGgiOjY2MjgsImZvcm1hdFRhaWwiOiJDbjAiLCJ0aW1lIjoiMjAxNS0wNC0wOFQxODo1Mjo1OVoifQ"
}
]
}

note

With the release of Docker Image Manifest V2 Schema 2, Docker Image Manifest V2 Schema 1 has been deprecated. This may lead to compatibility and vulnerability issues for images that have not been updated to Docker Image Manifest V2 Schema 2.

Docker Image Manifest V2 Schema 2

Then introduce the format of V2 Schema 2.

The V2 Schema 2 release has two main goals. The first is to allow multi-architecture images, which reference the image manifest of the platform-specific version of the image through a “fat manifest”. The second approach is to move the Docker engine to content-addressable images by supporting an image model in which the configuration of the image can be hashed to generate the ID of the image.

Manifest List

List of manifestsIt is part of the Docker V2 Schema 2 and OCI images.

Inventory lists allow you to use a single summary or tag to represent multiple forms of an image.

Manifest List

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 7143,
"digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f",
"platform": {
"architecture": "ppc64le",
"os": "linux",
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 7682,
"digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270",
"platform": {
"architecture": "amd64",
"os": "linux",
"features": [
"sse4"
]
}
}
]
}
Image manifest

Example image manifest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
"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"
}
]
}

How do I upgrade Docker V1 or Manifest V2 Schema 1 to: Docker Image Manifest V2 Schema 2?

  1. Use the old Docker V1 or Manifest V2 Schema 1 docker pull Get down;
  2. Then use the new version of Docker docker push Go to the image repository

Doing so will automatically convert the image to use the latest image manifest specification.

Or you can upgrade like this:

  1. You can do this by updating the Dockerfile FROM statement to re-build the image. If your image manifest is out of date, download it from the Dockerfile from Images extracted in the statement may also be out of date.

OCI format

The OCI format is a container image specification based on the Docker Image Manifest Version 2 Schema 2 format. The specification defines how to create an OCI Image (usually done by a build system) and output itImage manifestFile system (mirroring layer) serializationandMirror configuration。 The following is a brief comparison with Docker with the image list, and more will not be expanded in detail.

Image Index

Image IndexEquivalent to a Manifest List in an OCI image.

Like an inventory list, an image index inventory refers to multiple image manifests. Image indexes are useful for multiplatform images.

Example image index

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
"schemaVersion": 2,
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 7143,
"digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f",
"platform": {
"architecture": "ppc64le",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 7682,
"digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270",
"platform": {
"architecture": "amd64",
"os": "linux"
}
}
],
"annotations": {
"com.example.key1": "value1",
"com.example.key2": "value2"
}
}

Image manifest

Example image manifest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
"schemaVersion": 2,
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"size": 7023,
"digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7"
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 32654,
"digest": "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0"
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 16724,
"digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b"
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 73109,
"digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736"
}
],
"annotations": {
"com.example.key1": "value1",
"com.example.key2": "value2"
}
}

Summary of image format differences

The first is the Docker V1 image, which is a very old and deprecated image format, which was not considered multi-architecture and multi-platform (such as x86 and arm images) when Docker first came out, so usually Docker V1 images only have x86 platform images. Note: Do not use it again, if you do, please upgrade to Docker Image Manifest V2 Schema 2 or OCI format as soon as possible

Then there’s Docker Image Manifest V2 Schema 1, which is a transitional format, compatible with Docker V1 and Docker Image Manifest V2 to make it more complex, and its role is only for transition rather than long-term use. Note: Do not use it again, if you do, please upgrade to Docker Image Manifest V2 Schema 2 or OCI format as soon as possible

Finally, the Docker Image Manifest V2 Schema 2 and OCI format, OCI’s main reference is the Docker Image Manifest V2 Schema 2 format, the two are compatible, which answers the above question: “Can Docker images still be used?” – Yes, it can be used."

However, there are differences in details such as media type and compression method, some of which include:

  • On the manifest:
    • The Media Type for Docker Image Manifest V2 Schema 2 is:"application/vnd.docker.distribution.manifest.list.v2+json"
    • And OCI is:"application/vnd.oci.image.manifest.v1+json"
  • On each layer of mirroring:
    • The Media Type for Docker Image Manifest V2 Schema 2 is:"application/vnd.docker.image.rootfs.diff.tar.gzip"
    • OCI’s Media Type is:application/vnd.oci.image.layer.v1.tar+gzip or application/vnd.oci.image.layer.v1.tar and other types.

It is precisely because of these differences that even if the image is identical, the digest and image sizes of the two are not the same.

So this also explains “Then why was the Docker image found to be incompatible with the Containerd image?”

  1. “Can’t be used by Docker?” - It may be caused by too low docker version;
  2. “Docker push can’t be covered?” - Because even if the image is identical, the digest and image size of the two are not the same. So it can’t be overwritten.

My suggestion

For mirroring, because OCI mainly references Docker Image Manifest V2 Schema 2, and Docker Image Manifest V2 Schema 2 is an implementation of OCI. So the images generated by newer versions of Docker, containerd and CRI-O can extract these images and run them.

Either way:

  1. The image build method remains the same, and the image is still built using Docker (note that the Docker version should be newer, make sure that the image built is: Docker Image Manifest V2 Schema 2 format)
  2. Change the image build tool to no longer use Docker, but use the image build tool that can build OCI format.

You can choose according to the actual situation.


K8S 1.20 deprecates the difference between Docker and OCI image formats for Docker assessment
https://e-whisper.com/posts/7740/
Author
east4ming
Posted on
November 7, 2021
Licensed under