Fix empty `Manifests` field for multi-platform images that have no
platform blobs available locally.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
While the endpoint returns a detailed information about its children, it
doesn't actually expose the descriptor of the root OCI index/manifest
list.
This commits adds the target description to the returned JSON.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
daemon/containerd/image_list.go:162:3: The copy of the 'for' variable "img" can be deleted (Go 1.22+) (copyloopvar)
img := img
^
daemon/containerd/image_delete_test.go:222:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
daemon/containerd/image_list_test.go:89:3: The copy of the 'for' variable "count" can be deleted (Go 1.22+) (copyloopvar)
count := count
^
daemon/containerd/image_list_test.go:306:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
daemon/containerd/image_test.go:145:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
daemon/containerd/platform_matchers_test.go:131:4: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
daemon/containerd/platform_matchers_test.go:134:5: The copy of the 'for' variable "strict" can be deleted (Go 1.22+) (copyloopvar)
strict := strict
^
daemon/containerd/platform_matchers_test.go:159:7: The copy of the 'for' variable "p" can be deleted (Go 1.22+) (copyloopvar)
p := p
^
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
The `manifests` option, as used for the `--tree` option on `docker image ls`
currently sorts manifests to put those that are present first. The intent was
to present "available" images at the top of each tree, followed by images that
were not pulled.
However, there's some limitations to this. First of all, the current approach
makes the output non-deterministic as the order in which variants are pulled
determines the order in which they're presented, i.e., the last pulled variant
is returned first (I omitted some variants in the example for brevity);
Here's the result of pulling `linux/riscv64`, then pulling `linux/arm64`;
docker pull --platform=linux/riscv64 alpine:latest
docker image ls -a --tree
IMAGE ID DISK USAGE CONTENT SIZE USED
alpine:latest beefdbd8a1da 10.6MB 3.37MB
├─ linux/riscv64 80cde017a105 10.6MB 3.37MB
├─ linux/amd64 33735bd63cf8 0B 0B
└─ linux/arm64/v8 9cee2b382fe2 0B 0B
docker pull --platform=linux/arm64 alpine:latest
docker image ls -a --tree
IMAGE ID DISK USAGE CONTENT SIZE USED
alpine:latest beefdbd8a1da 24.2MB 7.46MB
├─ linux/riscv64 80cde017a105 10.6MB 3.37MB
├─ linux/arm64/v8 9cee2b382fe2 13.6MB 4.09MB
└─ linux/amd64 33735bd63cf8 0B 0B
Repeating the steps but in reverse order results in the output to be reversed;
docker image rm alpine:latest
docker pull --platform=linux/arm64 alpine:latest
docker image ls -a --tree
IMAGE ID DISK USAGE CONTENT SIZE USED
alpine:latest beefdbd8a1da 13.6MB 4.09MB
├─ linux/arm64/v8 9cee2b382fe2 13.6MB 4.09MB
├─ linux/amd64 33735bd63cf8 0B 0B
└─ linux/riscv64 80cde017a105 0B 0B
docker image ls -a --tree
IMAGE ID DISK USAGE CONTENT SIZE USED
alpine:latest beefdbd8a1da 24.2MB 7.46MB
├─ linux/riscv64 80cde017a105 10.6MB 3.37MB
├─ linux/arm64/v8 9cee2b382fe2 13.6MB 4.09MB
└─ linux/amd64 33735bd63cf8 0B 0B
The second limitation is that order sometimes matters; when matching a
platform from a manifest-index, implementations may find multiple suitable
candidates. In most cases the _most_ suitable candidate can be selected
(e.g., prefer `linux/arm/v7` over `linux/arm/v6`), but manifest-indices do
allow multiple entries for the same platform, in which case implementations
match the first entry found.
While these situations will be less common (and usually due to incorect use
of tooling such as `docker manifest`), being able to observe the order in
which manifests appeared in the index can help debugging or help the user
understand why a specific variant was selected.
We should therefore not re-order these manifests, and return them in the
order in which they appeared. If we decide to present "present" variants
before "non-present" variants, we can do this ordering on the client side.
With this patch applied;
docker pull --quiet --platform=linux/riscv64 alpine:latest
docker pull --quiet --platform=linux/arm64 alpine:latest
docker image ls --tree alpine
IMAGE ID DISK USAGE CONTENT SIZE USED
alpine:latest beefdbd8a1da 24.2MB 7.46MB
├─ linux/amd64 33735bd63cf8 0B 0B
├─ linux/arm/v6 50f635c8b04d 0B 0B
├─ linux/arm/v7 f2f82d424957 0B 0B
├─ linux/arm64/v8 9cee2b382fe2 13.6MB 4.09MB
├─ linux/386 b3e87f642f5c 0B 0B
├─ linux/ppc64le c7a6800e3dc5 0B 0B
├─ linux/riscv64 80cde017a105 10.6MB 3.37MB
└─ linux/s390x 2b5b26e09ca2 0B 0B
Which matches the order of the manifests in the index:
docker buildx imagetools inspect --raw alpine:latest | jq -c .manifests[].platform
{"architecture":"amd64","os":"linux"}
{"architecture":"arm","os":"linux","variant":"v6"}
{"architecture":"arm","os":"linux","variant":"v7"}
{"architecture":"arm64","os":"linux","variant":"v8"}
{"architecture":"386","os":"linux"}
{"architecture":"ppc64le","os":"linux"}
{"architecture":"riscv64","os":"linux"}
{"architecture":"s390x","os":"linux"}
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Before this, the image list would not show images that are not a valid
container image, but could be a valid artifact.
While they're not directly usable by docker, we should still show them
so the user can still discover them and at least be able to delete them.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Add `Manifests` field to `ImageSummary` which exposes all image
manifests (which includes other blobs using the image media type, like
buildkit attestations).
There's also a new `manifests` query field that needs to be set in order
for the response to contain the new information.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Switch to use github.com/containerd/platforms module, because containerd's
platforms package has moved to a separate module. This allows updating the
platforms parsing independent of the containerd module itself.
The package in containerd is deprecated, but kept as an alias to provide
compatibility between codebases.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Don't fail-fast when encountering an image that targets an unexpected
descriptor (neither a manifest nor index). Log a warning instead.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Benchmark the `Images` implementation (image list) against an image
store with 10, 100 and 1000 random images. Currently the images are
single-platform only.
The images are generated randomly, but a fixed seed is used so the
actual testing data will be the same across different executions.
Because the content store is not a real containerd image store but a
local implementation, a small delay (500us) is added to each content
store method call. This is to simulate a real-world usage where each
containerd client call requires a gRPC call.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>