[c8d] improve `docker image ls --tree` for images with multiple names/tags
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 6.1k
- Forks
- 2.2k
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 43
Description
Description
- relates to https://github.com/docker/cli/pull/4982
If an image is tagged under multiple names, only a single one of them is shown as tree, and for other variants, only the name is shown;
docker image ls --tree
IMAGE ID DISK USAGE CONTENT SIZE USED
alpine:3.20
alpine:latest beefdbd8a1da 13.6MB 4.09MB
├─ linux/arm64/v8 9cee2b382fe2 13.6MB 4.09MB
├─ linux/amd64 33735bd63cf8 0B 0B
├─ linux/arm/v6 50f635c8b04d 0B 0B
├─ linux/arm/v7 f2f82d424957 0B 0B
├─ linux/386 b3e87f642f5c 0B 0B
├─ linux/ppc64le c7a6800e3dc5 0B 0B
├─ linux/riscv64 80cde017a105 0B 0B
└─ linux/s390x 2b5b26e09ca2 0B 0B
hello-world:latest
registry.docker.com/library/hello-world:latest d211f485f2dd 21kB 4.64kB ✔
├─ linux/arm64/v8 2d4e459f4ecb 21kB 4.64kB ✔
├─ linux/amd64 e2fc4e5012d1 0B 0B
├─ linux/arm/v5 c2d891e5c2fb 0B 0B
├─ linux/arm/v6 1363c810cc39 0B 0B
├─ linux/arm/v7 20aea1c63c90 0B 0B
├─ linux/386 dbbd3cf66631 0B 0B
├─ linux/mips64le c19784034d46 0B 0B
├─ linux/ppc64le f0c95f1ebb50 0B 0B
├─ linux/riscv64 8d064a6fc27f 0B 0B
├─ linux/s390x 65f4b0d18025 0B 0B
├─ windows/amd64 c8e4ce54c77a 0B 0B
└─ windows/amd64 021ddc79e078 0B 0B
To reproduce;
$ docker pull --quiet alpine:3.20
docker.io/library/alpine:3.20
$ docker pull --quiet alpine:latest
docker.io/library/alpine:latest
$ docker image ls --tree
IMAGE ID DISK USAGE CONTENT SIZE USED
alpine:3.20
alpine:latest beefdbd8a1da 13.6MB 4.09MB
├─ linux/arm64/v8 9cee2b382fe2 13.6MB 4.09MB
├─ linux/amd64 33735bd63cf8 0B 0B
├─ linux/arm/v6 50f635c8b04d 0B 0B
├─ linux/arm/v7 f2f82d424957 0B 0B
├─ linux/386 b3e87f642f5c 0B 0B
├─ linux/ppc64le c7a6800e3dc5 0B 0B
├─ linux/riscv64 80cde017a105 0B 0B
└─ linux/s390x 2b5b26e09ca2 0B 0B
We should either show each of those images separately;
$ docker image ls --tree
IMAGE ID DISK USAGE CONTENT SIZE USED
alpine:3.20 beefdbd8a1da 13.6MB 4.09MB
├─ linux/arm64/v8 9cee2b382fe2 13.6MB 4.09MB
├─ linux/amd64 33735bd63cf8 0B 0B
├─ linux/arm/v6 50f635c8b04d 0B 0B
├─ linux/arm/v7 f2f82d424957 0B 0B
├─ linux/386 b3e87f642f5c 0B 0B
├─ linux/ppc64le c7a6800e3dc5 0B 0B
├─ linux/riscv64 80cde017a105 0B 0B
└─ linux/s390x 2b5b26e09ca2 0B 0B
alpine:latest beefdbd8a1da 13.6MB 4.09MB
├─ linux/arm64/v8 9cee2b382fe2 13.6MB 4.09MB
├─ linux/amd64 33735bd63cf8 0B 0B
├─ linux/arm/v6 50f635c8b04d 0B 0B
├─ linux/arm/v7 f2f82d424957 0B 0B
├─ linux/386 b3e87f642f5c 0B 0B
├─ linux/ppc64le c7a6800e3dc5 0B 0B
├─ linux/riscv64 80cde017a105 0B 0B
└─ linux/s390x 2b5b26e09ca2 0B 0B
Or, if we want to indicate "this is the same image, but tagged with multiple names" find some format where we group them;
$ docker image ls --tree
IMAGE ID DISK USAGE CONTENT SIZE USED
alpine:3.20, alpine:latest beefdbd8a1da 13.6MB 4.09MB
├─ linux/arm64/v8 9cee2b382fe2 13.6MB 4.09MB
├─ linux/amd64 33735bd63cf8 0B 0B
├─ linux/arm/v6 50f635c8b04d 0B 0B
├─ linux/arm/v7 f2f82d424957 0B 0B
├─ linux/386 b3e87f642f5c 0B 0B
├─ linux/ppc64le c7a6800e3dc5 0B 0B
├─ linux/riscv64 80cde017a105 0B 0B
└─ linux/s390x 2b5b26e09ca2 0B 0B
Unfortunately, images don't have a "canonical" name, otherwise we could've put the canonical name in the first column, and an "optional" column for additional names.
Grouping such variants may not work well though, as (in my first example) images could originate from / have been tagged for multiple registries, or have many different tags, in which case the IMAGE column would be too wide to remain useful;
docker image ls --tree
IMAGE ID DISK USAGE CONTENT SIZE USED
hello-world:latest, registry.docker.com/library/hello-world:latest d211f485f2dd 21kB 4.64kB ✔
├─ linux/arm64/v8 2d4e459f4ecb 21kB 4.64kB ✔
├─ linux/amd64 e2fc4e5012d1 0B 0B
├─ linux/arm/v5 c2d891e5c2fb 0B 0B
├─ linux/arm/v6 1363c810cc39 0B 0B
├─ linux/arm/v7 20aea1c63c90 0B 0B
├─ linux/386 dbbd3cf66631 0B 0B
├─ linux/mips64le c19784034d46 0B 0B
├─ linux/ppc64le f0c95f1ebb50 0B 0B
├─ linux/riscv64 8d064a6fc27f 0B 0B
├─ linux/s390x 65f4b0d18025 0B 0B
├─ windows/amd64 c8e4ce54c77a 0B 0B
└─ windows/amd64 021ddc79e078 0B 0B
From the API response; the API returns these images as a single item in the list, but lists all known tags under RepoTags ("RepoTags": ["alpine:3.20", "alpine:latest"]), so we should duplicate those entries when listing;
/ # curl -s --unix-socket /var/run/docker.sock http://localhost/v1.47/images/json?manifests=1 | jq .
[
{
"Containers": -1,
"Created": 1725662651,
"Id": "sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d",
"Labels": null,
"ParentId": "",
"Manifests": [
{
"ID": "sha256:9cee2b382fe2412cd77d5d437d15a93da8de373813621f2e4d406e3df0cf0e7c",
"Descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:9cee2b382fe2412cd77d5d437d15a93da8de373813621f2e4d406e3df0cf0e7c",
"size": 528,
"platform": {
"architecture": "arm64",
"os": "linux",
"variant": "v8"
}
},
"Available": true,
"Size": {
"Content": 4089660,
"Total": 13575996
},
"Kind": "image",
"ImageData": {
"Platform": {
"architecture": "arm64",
"os": "linux",
"variant": "v8"
},
"Size": {
"Unpacked": 9486336
},
"Containers": null
}
},
{
"ID": "sha256:33735bd63cf84d7e388d9f6d297d348c523c044410f553bd878c6d7829612735",
"Descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:33735bd63cf84d7e388d9f6d297d348c523c044410f553bd878c6d7829612735",
"size": 528,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"Available": false,
"Size": {
"Content": 0,
"Total": 0
},
"Kind": "image",
"ImageData": {
"Platform": {
"architecture": "amd64",
"os": "linux"
},
"Size": {
"Unpacked": 0
},
"Containers": null
}
},
{
"ID": "sha256:50f635c8b04d86dde8a02bcd8d667ba287eb8b318c1c0cf547e5a48ddadea1be",
"Descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:50f635c8b04d86dde8a02bcd8d667ba287eb8b318c1c0cf547e5a48ddadea1be",
"size": 528,
"platform": {
"architecture": "arm",
"os": "linux",
"variant": "v6"
}
},
"Available": false,
"Size": {
"Content": 0,
"Total": 0
},
"Kind": "image",
"ImageData": {
"Platform": {
"architecture": "arm",
"os": "linux",
"variant": "v6"
},
"Size": {
"Unpacked": 0
},
"Containers": null
}
},
{
"ID": "sha256:f2f82d42495723c4dc508fd6b0978a5d7fe4efcca4282e7aae5e00bcf4057086",
"Descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:f2f82d42495723c4dc508fd6b0978a5d7fe4efcca4282e7aae5e00bcf4057086",
"size": 528,
"platform": {
"architecture": "arm",
"os": "linux",
"variant": "v7"
}
},
"Available": false,
"Size": {
"Content": 0,
"Total": 0
},
"Kind": "image",
"ImageData": {
"Platform": {
"architecture": "arm",
"os": "linux",
"variant": "v7"
},
"Size": {
"Unpacked": 0
},
"Containers": null
}
},
{
"ID": "sha256:b3e87f642f5c48cdc7556c3e03a0d63916bd0055ba6edba7773df3cb1a76f224",
"Descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:b3e87f642f5c48cdc7556c3e03a0d63916bd0055ba6edba7773df3cb1a76f224",
"size": 528,
"platform": {
"architecture": "386",
"os": "linux"
}
},
"Available": false,
"Size": {
"Content": 0,
"Total": 0
},
"Kind": "image",
"ImageData": {
"Platform": {
"architecture": "386",
"os": "linux"
},
"Size": {
"Unpacked": 0
},
"Containers": null
}
},
{
"ID": "sha256:c7a6800e3dc569a2d6e90627a2988f2a7339e6f111cdf6a0054ad1ff833e99b0",
"Descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:c7a6800e3dc569a2d6e90627a2988f2a7339e6f111cdf6a0054ad1ff833e99b0",
"size": 528,
"platform": {
"architecture": "ppc64le",
"os": "linux"
}
},
"Available": false,
"Size": {
"Content": 0,
"Total": 0
},
"Kind": "image",
"ImageData": {
"Platform": {
"architecture": "ppc64le",
"os": "linux"
},
"Size": {
"Unpacked": 0
},
"Containers": null
}
},
{
"ID": "sha256:80cde017a10529a18a7274f70c687bb07c4969980ddfb35a1b921fda3a020e5b",
"Descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:80cde017a10529a18a7274f70c687bb07c4969980ddfb35a1b921fda3a020e5b",
"size": 528,
"platform": {
"architecture": "riscv64",
"os": "linux"
}
},
"Available": false,
"Size": {
"Content": 0,
"Total": 0
},
"Kind": "image",
"ImageData": {
"Platform": {
"architecture": "riscv64",
"os": "linux"
},
"Size": {
"Unpacked": 0
},
"Containers": null
}
},
{
"ID": "sha256:2b5b26e09ca2856f50ac88312348d26c1ac4b8af1df9f580e5cf465fd76e3d4d",
"Descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:2b5b26e09ca2856f50ac88312348d26c1ac4b8af1df9f580e5cf465fd76e3d4d",
"size": 528,
"platform": {
"architecture": "s390x",
"os": "linux"
}
},
"Available": false,
"Size": {
"Content": 0,
"Total": 0
},
"Kind": "image",
"ImageData": {
"Platform": {
"architecture": "s390x",
"os": "linux"
},
"Size": {
"Unpacked": 0
},
"Containers": null
}
}
],
"RepoDigests": [
"alpine@sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d"
],
"RepoTags": [
"alpine:3.20",
"alpine:latest"
],
"SharedSize": -1,
"Size": 13575996
}
]
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the docker image ls --tree command and the /v1.47/images/json?manifests=1 response described in the issue, especially RepoTags. Compare how multiple tags are represented in the current tree output, then determine a presentation that handles duplicate names without making the IMAGE column unusable. Done means the behavior and expected output are agreed and covered for images with multiple tags.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, go
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100