c8d: Use maximum native platform for matching#52773
c8d: Use maximum native platform for matching#52773
Conversation
c510f2d to
5a40751
Compare
|
Related PR: containerd/platforms#7 |
5a40751 to
ef5b04e
Compare
| p := platforms.DefaultSpec() | ||
| if p.Architecture == "amd64" { | ||
| p.Variant = archvariant.AMD64Variant() |
There was a problem hiding this comment.
Hm... is this something that should be fixed in containerd/platforms ? Looks like it has support for ARM, but not x86; also looks like there may be consistency between platforms;
moby/vendor/github.com/containerd/platforms/cpuinfo_other.go
Lines 26 to 37 in e0f2f6a
moby/vendor/github.com/containerd/platforms/cpuinfo_linux.go
Lines 75 to 90 in e0f2f6a
moby/vendor/github.com/containerd/platforms/cpuinfo_linux.go
Lines 140 to 145 in e0f2f6a
There was a problem hiding this comment.
Ultimately containerd/platforms should probably have a helper for this, but in the meantime we need to fix this on our side.
|
Running this docker-in-docker I'm only getting the base arch on my test image (cpuguy83/test-amd64-subarch). |
Image details: {
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.index.v1+json",
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:b0e32519fd3a105f05077ff23435f1e765aef559276c40e9cfb30ae7566c0881",
"size": 480,
"platform": {
"architecture": "amd64",
"os": "linux",
"variant": "v3"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:5c7289f3ea2f993df6165eedce27af0f89c7a92a96ea1674b0343bdc395356ea",
"size": 480,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:95b800ddba20f213ae52d51c11c1945f034649c1ed36c9ed307724df9951fb0b",
"size": 564,
"annotations": {
"vnd.docker.reference.digest": "sha256:b0e32519fd3a105f05077ff23435f1e765aef559276c40e9cfb30ae7566c0881",
"vnd.docker.reference.type": "attestation-manifest"
},
"platform": {
"architecture": "unknown",
"os": "unknown"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:a4f33a94fda8eb41395d1c49185aaabf28b44cceec35564e1351258fa0e1a91e",
"size": 564,
"annotations": {
"vnd.docker.reference.digest": "sha256:5c7289f3ea2f993df6165eedce27af0f89c7a92a96ea1674b0343bdc395356ea",
"vnd.docker.reference.type": "attestation-manifest"
},
"platform": {
"architecture": "unknown",
"os": "unknown"
}
}
]
} |
|
Oh, interesting: root@f469b75813a2:/go/src/github.com/docker/docker# docker run -it --rm cpuguy83/test-amd64-subarch
Unable to find image 'cpuguy83/test-amd64-subarch:latest' locally
latest: Pulling from cpuguy83/test-amd64-subarch
a278e1f259fb: Pull complete
ff353f22e1e2: Download complete
Digest: sha256:1598e33bd98eb272b771fb2207261b9dbf4cc7c5c683e42d45d80470468f403b
Status: Downloaded newer image for cpuguy83/test-amd64-subarch:latest
Hello from amd64/v1
root@f469b75813a2:/go/src/github.com/docker/docker# docker run --platform linux/amd64/v3 -it --rm cpuguy83/test-amd64-subarch
Unable to find image 'cpuguy83/test-amd64-subarch:latest' locally
latest: Pulling from cpuguy83/test-amd64-subarch
3d9b1ff0e3ff: Pull complete
f7500c9d6b27: Download complete
Digest: sha256:1598e33bd98eb272b771fb2207261b9dbf4cc7c5c683e42d45d80470468f403b
Status: Image is up to date for cpuguy83/test-amd64-subarch:latest
Hello from amd64/v3
root@f469b75813a2:/go/src/github.com/docker/docker# docker run -it --rm cpuguy83/test-amd64-subarch
Hello from amd64/v3
root@f469b75813a2:/go/src/github.com/docker/docker# docker run --platform linux/amd64/v1 -it --rm cpuguy83/test-amd64-subarch
Hello from amd64/v1
root@f469b75813a2:/go/src/github.com/docker/docker# docker run -it --rm cpuguy83/test-amd64-subarch
Hello from amd64/v3 |
| } | ||
|
|
||
| p := platforms.Default() | ||
| p := i.hostPlatformMatcher() |
There was a problem hiding this comment.
This p never reaches client.Pull, so the variant-aware host platform isn't applied at pull time.
When platform == nil, no containerd.WithPlatform(...) opt is added (the opts block higher up only sets it when a platform is requested), and p is only handed to c8dimages.Check below — the progress check. In vendored client/pull.go (L63-67), an empty Platforms makes client.Pull fall back to c.platform, which is the containerd client default (platforms.Default(), plain amd64, no variant) since we construct the client without WithDefaultPlatform in daemon.go.
Net effect: a plain docker pull/docker run on a v4 host downloads and unpacks the v1 manifest. LimitManifests (limit 1) sorts the index by the variant-less matcher, so plain amd64 wins over amd64/v3. The store-side matching this PR adds is correct — which is why once v3 is in the store a subsequent plain docker run resolves to v3 — but the initial pull selection bypasses it.
Repro on a v4 host with an index containing amd64 + amd64/v3:
docker run <img>->Hello from amd64/v1docker run --platform linux/amd64/v3 <img>-> pulls v3docker run <img>-> nowHello from amd64/v3
Suggested fix: pass the host spec through to the pull when no platform was requested, e.g. always add containerd.WithPlatform(platforms.FormatAll(i.hostPlatformSpec())) (using *platform when set). That gives containerd Only(amd64/v4), whose fallback vector still matches plain amd64, so it selects v3 here and stays consistent with the store-side matcher.
Review from Claude Opus 4.8
There was a problem hiding this comment.
Thanks, I pushed a commit to address this. Can you verify on your side it's ok now?
It's late now and I didn't manage to get to my amd64 machine to test this properly 🙈
There was a problem hiding this comment.
Now the behavior is less suprising, but it only does v3 when specifically requested.
Not sure if that's the intent (certainly for builds it likely should be?).
Details
root@95139424b3c3:/go/src/github.com/docker/docker# docker run -it --rm cpuguy83/test-amd64-subarch
Unable to find image 'cpuguy83/test-amd64-subarch:latest' locally
latest: Pulling from cpuguy83/test-amd64-subarch
a278e1f259fb: Pull complete
ff353f22e1e2: Download complete
Digest: sha256:1598e33bd98eb272b771fb2207261b9dbf4cc7c5c683e42d45d80470468f403b
Status: Downloaded newer image for cpuguy83/test-amd64-subarch:latest
Hello from amd64/v1
root@95139424b3c3:/go/src/github.com/docker/docker# docker run -it --rm cpuguy83/test-amd64-subarch
Hello from amd64/v1
root@95139424b3c3:/go/src/github.com/docker/docker# docker run -it --rm --platform linux/amd64/v3 cpuguy83/test-amd64-subarch
Unable to find image 'cpuguy83/test-amd64-subarch:latest' locally
latest: Pulling from cpuguy83/test-amd64-subarch
3d9b1ff0e3ff: Pull complete
f7500c9d6b27: Download complete
Digest: sha256:1598e33bd98eb272b771fb2207261b9dbf4cc7c5c683e42d45d80470468f403b
Status: Image is up to date for cpuguy83/test-amd64-subarch:latest
Hello from amd64/v3
root@95139424b3c3:/go/src/github.com/docker/docker# docker run -it --rm cpuguy83/test-amd64-subarch
Hello from amd64/v1
There was a problem hiding this comment.
Oh I see now, it's only the case if you have amd64/v1 locally.
If you don't then it will still prefer pulling v3:
root@1e364b189a46:/go/src/github.com/docker/docker# docker images
i Info → U In Use
IMAGE ID DISK USAGE CONTENT SIZE EXTRA
root@1e364b189a46:/go/src/github.com/docker/docker# docker run cpuguy83/test-amd64-subarch:latest
Unable to find image 'cpuguy83/test-amd64-subarch:latest' locally
latest: Pulling from cpuguy83/test-amd64-subarch
3d9b1ff0e3ff: Pull complete
f7500c9d6b27: Download complete
Digest: sha256:1598e33bd98eb272b771fb2207261b9dbf4cc7c5c683e42d45d80470468f403b
Status: Downloaded newer image for cpuguy83/test-amd64-subarch:latest
Hello from amd64/v3
but if you have v1 already, it will just use this one using the "best locally available platform" logic.
This is also visible with non-native platforms:
root@1e364b189a46:/go/src/github.com/docker/docker# docker pull --linux/arm64 alpine
root@1e364b189a46:/go/src/github.com/docker/docker# docker run alpine
WARNING: The requested image's platform (linux/arm64/v8) does not match the detected host platform (linux/amd64/v3) and no specific platform was requested
See: #50043
There was a problem hiding this comment.
Oh, looks like I must have had an issue checking out the branch before (stale git lock file).
Fixed it and now this is running as expected.
Tests should replace the detected host platform, not the matcher built from it. Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Introduce `hostPlatformSpec` as a replacement, so we can decouple from containerd platforms logic and override for tests. Default image-store operations should share the same host platform preference as pulls, otherwise list, identity cache, and classic-builder selection can still rank plain linux/amd64 ahead of compatible amd64 variants. Route those unspecified-platform paths through the ImageService host matcher so amd64 variant fallback stays consistent. Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
containerd's default platform spec does not include amd64 CPU variants. Populate the host platform spec with the detected amd64 compatibility level, using the existing go-archvariant dependency, so containerd image-store matchers can prefer compatible variant manifests. Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Always pass the pull platform through WithPlatform. For implicit pulls this is the host platform, including the amd64 variant; for explicit pulls it remains the requested platform. This doesn't make the platform matching strict - containerd resolves WithPlatform through platforms.Only, so linux/amd64/v3 still falls back to compatible lower or plain linux/amd64 manifests when no v3 manifest exists. This keeps initial pull selection consistent with store-side matching and preserves compatibility with non-variant amd64 images. Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
ef5b04e to
d98515d
Compare
Summary
The containerd image-store path used
platforms.Default()in several unspecified-platform selection paths.On amd64, containerd's default platform does not include the detected x86-64 micro-architecture variant, so a host capable of
linux/amd64/v4can behave like plainlinux/amd64when selecting manifests.That can skip compatible
linux/amd64/v3orlinux/amd64/v2entries and report that no suitable manifest exists.Release notes (optional)
A picture of a cute animal (not mandatory but encouraged)