From fafbfcb8c7cbc9db7fd51b679432e188fe603dce Mon Sep 17 00:00:00 2001 From: Rodrigo Campos Date: Mon, 16 Feb 2026 12:03:54 +0100 Subject: [PATCH] integration: Fix TestImageLoad() failure on CI If docker in the host is configured to use the containerd image format, then the docker pull/save commands above download the multi-platform image. IOW, the index.json has references to the other platforms SHAs. This references to things that are not present (the artifacts for other platforms) is what make `ctr` fail. However, if we specify a platform, then ctr ignores the other platforms and the import works just fine. To try this locally, you can: $ docker pull ghcr.io/containerd/busybox:1.36 $ docker save ghcr.io/containerd/busybox:1.36 -o image.tar $ ctr images import --local=true image.tar The last command will fail if you are using the containerd image store in docker. If you specify the platform with --platform, it works fine. With docker overlayfs2 storage driver, if you untar the image you get only things relevant for your platform: ``` $ cat index.json | jq { "schemaVersion": 2, "mediaType": "application/vnd.oci.image.index.v1+json", "manifests": [ { "mediaType": "application/vnd.oci.image.manifest.v1+json", "digest": "sha256:4d6b13f2ddbe87da8d9dee3719df1723a6d768e511802e70d42ab15370c6eb24", "size": 401, "annotations": { "io.containerd.image.name": "ghcr.io/containerd/busybox:1.36", "org.opencontainers.image.ref.name": "1.36" } } ] } $ cat blobs/sha256/4d6b13f2ddbe87da8d9dee3719df1723a6d768e511802e70d42ab15370c6eb24 | jq { "schemaVersion": 2, "mediaType": "application/vnd.oci.image.manifest.v1+json", "config": { "mediaType": "application/vnd.oci.image.config.v1+json", "digest": "sha256:66ba00ad3de8677a3fa4bc4ea0fc46ebca0f14db46ca365e7f60833068dd0148", "size": 1457 }, "layers": [ { "mediaType": "application/vnd.oci.image.layer.v1.tar", "digest": "sha256:b64792c17e4ad443d16b218afb3a8f5d03ca0f4ec49b11c1a7aebe17f6c3c1d2", "size": 5096448 } ] } ``` But with the other you get for lot of other platforms too: ``` $ cat index.json | jq { "schemaVersion": 2, "mediaType": "application/vnd.oci.image.index.v1+json", "manifests": [ { "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json", "digest": "sha256:7b3ccabffc97de872a30dfd234fd972a66d247c8cfc69b0550f276481852627c", "size": 2295, "annotations": { "containerd.io/distribution.source.ghcr.io": "containerd/busybox", "io.containerd.image.name": "ghcr.io/containerd/busybox:1.36", "org.opencontainers.image.ref.name": "1.36" } } ] } $ cat blobs/sha256/7b3ccabffc97de872a30dfd234fd972a66d247c8cfc69b0550f276481852627c | jq { "manifests": [ { "digest": "sha256:907ca53d7e2947e849b839b1cd258c98fd3916c60f2e6e70c30edbf741ab6754", "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "platform": { "architecture": "amd64", "os": "linux" }, "size": 528 }, { "digest": "sha256:dde8e930c7b6a490f728e66292bc9bce42efc9bbb5278bae40e4f30f6e00fe8c", "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "platform": { "architecture": "arm", "os": "linux", "variant": "v5" }, "size": 528 }, { ... ``` You can switch to the containerd snapshotter in docker by adding this to the daemon.json: ``` { "features": { "containerd-snapshotter": true } } ``` Signed-off-by: Rodrigo Campos --- integration/image_load_test.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/integration/image_load_test.go b/integration/image_load_test.go index 25dfc1ecd6aff..a46cbea345411 100644 --- a/integration/image_load_test.go +++ b/integration/image_load_test.go @@ -67,8 +67,15 @@ func TestImageLoad(t *testing.T) { require.NoError(t, err, "ctr should be installed, make sure you've run `make install-deps`") // Add --local=true option since currently the transfer service // does not provide enough progress to avoid timeout + // and --platform to only check for manifests for this platform. The "ctr image import" + // command otherwise might fail, if the the above docker commands use the containerd image + // store, as in that case `docker save` produces OCI artifacts referencing manifests for + // other platforms that are not included in what we downloaded. By specifying a platform, we + // just ignore the references to other platforms. + platform := "--platform=" + goruntime.GOOS + "/" + goruntime.GOARCH output, err = exec.Command(ctr, "-address="+containerdEndpoint, - "-n=k8s.io", "images", "import", "--local=true", tar).CombinedOutput() + "-n=k8s.io", "images", "import", "--local=true", + platform, tar).CombinedOutput() require.NoError(t, err, "output: %q", output) t.Logf("make sure image is loaded")