Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

suggested improvements to docker image ls and docker image ls --tree for multi-platform #5560

Open
thaJeztah opened this issue Oct 20, 2024 · 7 comments
Labels
area/ux containerd-integration Issues and PRs related to containerd integration kind/enhancement

Comments

@thaJeztah
Copy link
Member

Description

The tree output currently uses the same sort order as the existing
non-tree output, and orders the images by "created" time in descending
order;

docker image ls
REPOSITORY       TAG       IMAGE ID       CREATED          SIZE
<none>           <none>    8262a6d8c38a   7 minutes ago    13.6MB
docker-cli-dev   latest    f5f0547476ee   12 minutes ago   762MB
nginx            alpine    2140dad235c1   2 weeks ago      76.7MB
alpine           latest    beefdbd8a1da   6 weeks ago      24.2MB

Sorting by the created date can be useful, e.g.;

  • The last built image appears at the top (so could be found through cutting
    the first line)
  • It's consistent with docker container ls / docker ps, which uses the
    same ordering, but also provides flags to get the last containers (-l,
    --latest, and -n, --last)

However, the CREATED has become less useful in various situations. For
example, "reproducible builds" tend to either leave the "created" date
unset, or use a fixed date (often resulting in images created "many years
ago").

The date also has some ambiguity; for multi-platform images, each image
can have its own "created" date (and built at a different time); which
date to show in the list?

The CREATED date also has been confusing at times. For example, an image
that was just pulled may have been built weeks ago, and now not showing at
the top of the list. But also situations where docker build was able to
use the build-cache, in which case the image wasn't updated, and as a result
the CREATED date of the image being in the past.

Finally, sorting by CREATED is confusing when using the new --tree output
of images. This output does not currently have a CREATED column, which
makes the output order seem "random". With the tree view being more verbose,
it may also be harder to find back images in the list when they're not sorted
in an easy to discover way (some platforms were omitted in the example below
to keep the example short).

$ docker image ls --tree

IMAGE                   ID             DISK USAGE   CONTENT SIZE   USED
docker-cli-dev:latest   f5f0547476ee        762MB          179MB    ✔
└─ linux/arm64          18ca7881145d        762MB          179MB    ✔

nginx:alpine            2140dad235c1       76.7MB         21.5MB
├─ linux/arm64/v8       d1f949a77b81       76.7MB         21.5MB
├─ linux/amd64          ae136e431e76           0B             0B
└─ linux/s390x          8c310bf29cfa           0B             0B

alpine:latest           beefdbd8a1da       24.2MB         7.46MB
├─ linux/riscv64        80cde017a105       10.6MB         3.37MB
├─ linux/arm64/v8       9cee2b382fe2       13.6MB         4.09MB
└─ linux/s390x          2b5b26e09ca2           0B             0B

Suggestions

I think there's a couple of options we have, short-term and longer term.

Short term

We should be careful changing the default order, at least for the current
presentation, as people may depend on this. However, the work on the --tree
output is part of future work to make the CLI more human-friendly, and to
provide a more modern look and feel. Such changes are a good opportunity
to make changes; those changes may be "breaking" changes, so we may need
some opt-in/opt-out options to help people transition.

Longer term

We may need more granular information about dates and usage of images (and
other content), such as:

1. Add a collapsed version of the --tree view

We should make a collapsed version of the --tree view. This layout can
become the default in future, but initially (and while we're still designing
these bits), we can make this an "opt-in" through the features option
in the CLI config (e.g. {"features": {"multiplatform-output": true}}.

The collapsed view will have the same columns as the expanded --tree view;

$ docker image ls

IMAGE                   ID             DISK USAGE   CONTENT SIZE   USED
<untagged>              20ad73eca911       13.6MB         4.09MB    ✔
<untagged>              b3e87f642f5c       13.6MB         4.09MB
<untagged>              8262a6d8c38a       13.6MB         4.09MB
docker-cli-dev:latest   f5f0547476ee        762MB          179MB    ✔
nginx:alpine            2140dad235c1       76.7MB         21.5MB
alpine:latest           beefdbd8a1da       24.2MB         7.46MB

This means that when using the --tree view, the layout stays the same,
but with more details shown;

$ docker image ls --tree

IMAGE                   ID             DISK USAGE   CONTENT SIZE   USED
<untagged>              20ad73eca911       13.6MB         4.09MB    ✔
└─ linux/arm64          1ab6fc68586e       13.6MB         4.09MB    ✔

<untagged>              b3e87f642f5c       13.6MB         4.09MB
└─ linux/arm64          1ab6fc68586e       13.6MB         4.09MB

<untagged>              8262a6d8c38a       13.6MB         4.09MB
└─ linux/arm64          1ab6fc68586e       13.6MB         4.09MB

docker-cli-dev:latest   f5f0547476ee        762MB          179MB    ✔
└─ linux/arm64          18ca7881145d        762MB          179MB    ✔

nginx:alpine            2140dad235c1       76.7MB         21.5MB
├─ linux/arm64/v8       d1f949a77b81       76.7MB         21.5MB
├─ linux/amd64          ae136e431e76           0B             0B
├─ linux/arm/v6         ae1ee4b63c14           0B             0B
├─ linux/arm/v7         20ad73eca911           0B             0B
├─ linux/386            1e69bfb21757           0B             0B
├─ linux/ppc64le        7fef8bcf8b6c           0B             0B
└─ linux/s390x          8c310bf29cfa           0B             0B

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
├─ linux/arm/v6         50f635c8b04d           0B             0B
├─ linux/arm/v7         f2f82d424957           0B             0B
├─ linux/386            b3e87f642f5c           0B             0B
├─ linux/ppc64le        c7a6800e3dc5           0B             0B
└─ linux/s390x          2b5b26e09ca2           0B             0B

2. Sort alphabetically by default

For the new layout, we can change the sort-order. I suggest that sorting
alphabetically (using natural-sort) would make sense. I think we should
also consider sorting <untagged> images last, as they may be less relevant
to the user:

$ docker image ls

IMAGE                   ID             DISK USAGE   CONTENT SIZE   USED
alpine:latest           beefdbd8a1da       24.2MB         7.46MB
docker-cli-dev:latest   f5f0547476ee        762MB          179MB    ✔
nginx:alpine            2140dad235c1       76.7MB         21.5MB
<untagged>              8262a6d8c38a       13.6MB         4.09MB    ✔
<untagged>              b3e87f642f5c       13.6MB         4.09MB 
<untagged>              8262a6d8c38a       13.6MB         4.09MB 

This means that when using the --tree view, the layout stays the same,
but with more details shown;

$ docker image ls --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
├─ linux/arm/v6         50f635c8b04d           0B             0B
├─ linux/arm/v7         f2f82d424957           0B             0B
├─ linux/386            b3e87f642f5c           0B             0B
├─ linux/ppc64le        c7a6800e3dc5           0B             0B
└─ linux/s390x          2b5b26e09ca2           0B             0B

docker-cli-dev:latest   f5f0547476ee        762MB          179MB    ✔
└─ linux/arm64          18ca7881145d        762MB          179MB    ✔

nginx:alpine            2140dad235c1       76.7MB         21.5MB
├─ linux/arm64/v8       d1f949a77b81       76.7MB         21.5MB
├─ linux/amd64          ae136e431e76           0B             0B
├─ linux/arm/v6         ae1ee4b63c14           0B             0B
├─ linux/arm/v7         20ad73eca911           0B             0B
├─ linux/386            1e69bfb21757           0B             0B
├─ linux/ppc64le        7fef8bcf8b6c           0B             0B
└─ linux/s390x          8c310bf29cfa           0B             0B

<untagged>              20ad73eca911       13.6MB         4.09MB    ✔
└─ linux/arm64          1ab6fc68586e       13.6MB         4.09MB    ✔

<untagged>              b3e87f642f5c       13.6MB         4.09MB
└─ linux/arm64          1ab6fc68586e       13.6MB         4.09MB

<untagged>              8262a6d8c38a       13.6MB         4.09MB
└─ linux/arm64          1ab6fc68586e       13.6MB         4.09MB

3. Use stable sort order for manifests

The --tree option on currently sorts manifests to put those that are present
first, and those that are not present (not pulled) after. 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;

$ docker pull --platform=linux/riscv64 alpine:latest
$ docker pull --platform=linux/arm64 alpine:latest
$ docker image ls -a --tree alpine

IMAGE                   ID             DISK USAGE   CONTENT SIZE   IN USE
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
├─ linux/arm/v6         50f635c8b04d           0B             0B
├─ linux/arm/v7         f2f82d424957           0B             0B
├─ linux/386            b3e87f642f5c           0B             0B
├─ linux/ppc64le        c7a6800e3dc5           0B             0B
└─ linux/s390x          2b5b26e09ca2           0B             0B

This makes the output non-deterministic, and lacking a LAST PULLED (or
something similar) field, can make it somewhat confusing.

The order in which variants appear in the manifest can be relevant, as
in some cases this order affects what image is pulled as "best match"
if no exact match is available for the host's native architecture, and
if multiple platforms variants are candidates.

I think we should default to present variants in the order they are included
in the manifest index. More details also in this PR:

$ docker pull --platform=linux/riscv64 alpine:latest
$ docker pull --platform=linux/arm64 alpine:latest
$ docker image ls -a --tree alpine

IMAGE                   ID             DISK USAGE   CONTENT SIZE   IN USE
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

4. Hide non-pulled images by default (TBD)

One option worth considering is to hide non-pulled platform variants
by default. Doing so would partially achieve the goal that sorting
the "available variants first" mentioned above, and it would make the
output shorter in most situations. In many cases, users may only have
the native variant of an image pulled.

We need to design a UX for this though; would --all be used to show
"all the things", or do we need a more granular option? ("all variants"
vs "all images, including dangling ones")

$ docker image ls --tree alpine

IMAGE                   ID             DISK USAGE   CONTENT SIZE   USED
alpine:latest           beefdbd8a1da       24.2MB         7.46MB
├─ linux/arm64/v8       9cee2b382fe2       13.6MB         4.09MB
└─ linux/riscv64        80cde017a105       10.6MB         3.37MB

5. Hide untagged images by default

We should consider re-defining the meaning of --all, as well as "dangling"
and "intermediate" images. Some of the "dangling" images definition originates
from the classic/legacy builder, which used the image store for build-cache;
each step in the Dockerfile resulted in an untagged image, but the image had
to be preserved to be used for its cache. Cleaning up those images was a manual
step, so the --all option was added to make them visible.

With BuildKit being the default builder now, cleaning up the build-cache is
handled separate from cleaning up images ( docker builder prune / docker buildx prune),
and BuildKit also provides automatic garbage collection of its buildcache.

While we don't (yet!) have automatic garbage collection for images, I think
we should have that at some point (at least opt-in), and hiding untagged
content would (IMO) be a good place to start, to show that's content eligible
for removal (if it's important to you, you should've put a ring on it, and
tagged or pushed it).

$ docker image ls

IMAGE                   ID             DISK USAGE   CONTENT SIZE   USED
alpine:latest           beefdbd8a1da       24.2MB         7.46MB
docker-cli-dev:latest   f5f0547476ee        762MB          179MB    ✔
nginx:alpine            2140dad235c1       76.7MB         21.5MB

Same, but --tree view:

$ docker image ls --tree

IMAGE                   ID             DISK USAGE   CONTENT SIZE   USED
alpine:latest           beefdbd8a1da       24.2MB         7.46MB
├─ linux/arm64/v8       9cee2b382fe2       13.6MB         4.09MB
└─ linux/riscv64        80cde017a105       10.6MB         3.37MB

docker-cli-dev:latest   f5f0547476ee        762MB          179MB    ✔
└─ linux/arm64          18ca7881145d        762MB          179MB    ✔

nginx:alpine            2140dad235c1       76.7MB         21.5MB
└─ linux/arm64/v8       d1f949a77b81       76.7MB         21.5MB

And -a / --all option to show all images, including un-tagged and those
not pulled;

$ docker image ls --tree

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

docker-cli-dev:latest   f5f0547476ee        762MB          179MB    ✔
└─ linux/arm64          18ca7881145d        762MB          179MB    ✔

nginx:alpine            2140dad235c1       76.7MB         21.5MB
├─ linux/amd64          ae136e431e76           0B             0B
├─ linux/arm/v6         ae1ee4b63c14           0B             0B
├─ linux/arm/v7         20ad73eca911           0B             0B
├─ linux/arm64/v8       d1f949a77b81       76.7MB         21.5MB
├─ linux/386            1e69bfb21757           0B             0B
├─ linux/ppc64le        7fef8bcf8b6c           0B             0B
└─ linux/s390x          8c310bf29cfa           0B             0B

<untagged>              20ad73eca911       13.6MB         4.09MB    ✔
└─ linux/arm64          1ab6fc68586e       13.6MB         4.09MB    ✔

<untagged>              b3e87f642f5c       13.6MB         4.09MB
└─ linux/arm64          1ab6fc68586e       13.6MB         4.09MB

<untagged>              8262a6d8c38a       13.6MB         4.09MB
└─ linux/arm64          1ab6fc68586e       13.6MB         4.09MB

Some parts may have to be looked into in more depth; there's still some
odd behavior that, while "by design", is surprising;

Related to that, we need to decide whether to hide untagged images if
they are still in use by a container, or consider those case (as they
(I think) require docker image rm --force) are still eligible for
garbage collecting (once the container is removed0, and thus should also
be hidden.

@thaJeztah
Copy link
Member Author

OK, was giving this some thought, following the discussion on #5556 (review).

Taking the following situation;

docker pull --quiet alpine:latest

docker tag alpine:latest docker.io/namespace/image:1
docker tag alpine:latest docker.io/namespace/image:1.0
docker tag alpine:latest docker.io/namespace/image:1.0.0
docker tag alpine:latest docker.io/namespace/image:latest


docker tag alpine:latest internal.example.com/namespace/image:1
docker tag alpine:latest internal.example.com/namespace/image:1.0
docker tag alpine:latest internal.example.com/namespace/image:1.0.0
docker tag alpine:latest internal.example.com/namespace/image:latest

Current

Currently, this shows as:

$ docker image ls --tree
IMAGE                                            ID             DISK USAGE   CONTENT SIZE   USED
alpine:latest
namespace/image:1
namespace/image:1.0
namespace/image:1.0.0
namespace/image:latest
internal.example.com/namespace/image:1
internal.example.com/namespace/image:1.0
internal.example.com/namespace/image:1.0.0
internal.example.com/namespace/image:latest      beefdbd8a1da       13.6MB         4.09MB
├─ 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           0B             0B
└─ linux/s390x                                   2b5b26e09ca2           0B             0B

Split per repository

We can split the list per repository, so that alpine, namespace/image and internal.example.com/namespace/image don't get clobbered together:

$ docker image ls --tree
IMAGE                                            ID             DISK USAGE   CONTENT SIZE   USED
alpine:latest                                    beefdbd8a1da       13.6MB         4.09MB
├─ 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           0B             0B
└─ linux/s390x                                   2b5b26e09ca2           0B             0B

namespace/image:1
namespace/image:1.0
namespace/image:1.0.0
namespace/image:latest
namespace/image:latest                           beefdbd8a1da       13.6MB         4.09MB
├─ 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           0B             0B
└─ linux/s390x                                   2b5b26e09ca2           0B             0B

internal.example.com/namespace/image:1
internal.example.com/namespace/image:1.0
internal.example.com/namespace/image:1.0.0
internal.example.com/namespace/image:latest      beefdbd8a1da       13.6MB         4.09MB
├─ 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           0B             0B
└─ linux/s390x                                   2b5b26e09ca2           0B             0B

Tree per repository

That would still make things slightly cluttered, so we could go one level deeper on trees, and if a repository has multiple tags for the same image, show those as a nesting one level deeper;

$ docker image ls --tree
IMAGE/TAGS                                       ID             DISK USAGE   CONTENT SIZE   USED
alpine:latest                                    beefdbd8a1da       13.6MB         4.09MB
├─ 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           0B             0B
└─ linux/s390x                                   2b5b26e09ca2           0B             0B


namespace/image                                  beefdbd8a1da       13.6MB         4.09MB
├─ namespace/image:1                             beefdbd8a1da            -              -
├─ namespace/image:1.0                           beefdbd8a1da            -              -
├─ namespace/image:1.0.0                         beefdbd8a1da            -              -
└─ namespace/image:latest                        beefdbd8a1da            -              -
   ├─ 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           0B             0B
   └─ linux/s390x                                2b5b26e09ca2           0B             0B

internal.example.com/namespace/image             beefdbd8a1da       13.6MB         4.09MB
├─ internal.example.com/namespace/image:1        beefdbd8a1da            -              -
├─ internal.example.com/namespace/image:1.0      beefdbd8a1da            -              -
├─ internal.example.com/namespace/image:1.0.0    beefdbd8a1da            -              -
└─ internal.example.com/namespace/image:latest   beefdbd8a1da            -              -
   ├─ 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           0B             0B
   └─ linux/s390x                                2b5b26e09ca2           0B             0B

thaJeztah added a commit to thaJeztah/cli that referenced this issue Oct 28, 2024
Nothing mergeable here, but this was me playing around; initially to see
if we could print the format such as suggested in docker#5560 (comment)

That output is shown in `TestTree`:

    IMAGE/TAGS ID                                    DISK USAGE          CONTENT SIZE        USED
    alpine:latest                                    beefdbd8a1da        13.6MB              4.09MB
    ├─ 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        0B                  0B
    └─ linux/s390x                                   2b5b26e09ca2        0B                  0B

    namespace/image                                  beefdbd8a1da        13.6MB              4.09MB
    ├─ namespace/image:1                             beefdbd8a1da        -                   -
    ├─ namespace/image:1.0                           beefdbd8a1da        -                   -
    ├─ namespace/image:1.0.0                         beefdbd8a1da        -                   -
    └─ namespace/image:latest                        beefdbd8a1da        -                   -
       ├─ 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        0B                  0B
       └─ linux/s390x                                2b5b26e09ca2        0B                  0B

    internal.example.com/namespace/image             beefdbd8a1da        13.6MB              4.09MB
    ├─ internal.example.com/namespace/image:1        beefdbd8a1da        -                   -
    ├─ internal.example.com/namespace/image:1.0      beefdbd8a1da        -                   -
    ├─ internal.example.com/namespace/image:1.0.0    beefdbd8a1da        -                   -
    └─ internal.example.com/namespace/image:latest   beefdbd8a1da        -                   -
       ├─ 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        0B                  0B
       └─ linux/s390x                                2b5b26e09ca2        0B                  0B

The second bit was to see if we could make the tree output more align
with other output formats;

- Most of our commands allow passing a `--format`, including for (e.g.) `table`
- We want the tree view to also support, e.g. `--no-trunc`, which means that
  some columns will be wider.
- If we use a tabwriter for printing, we can have it handle the column-sizing
  for us.
- And if we do, we could let the user pass a custom format, and still print
  it as a tree.

e.g., a format could be;

    --format 'tree {.Image}}\t{{.Digest}}\t{{.InUse}}'

Which would output something like

    IMAGE                   ID             USED
    alpine:latest           beefdbd8a1da    ✔
    ├─ linux/amd64          33735bd63cf8
    ├─ linux/arm/v6         50f635c8b04d
    ├─ linux/arm/v7         f2f82d424957
    ├─ linux/arm64/v8       9cee2b382fe2    ✔
    ├─ linux/386            b3e87f642f5c
    ├─ linux/ppc64le        c7a6800e3dc5
    ├─ linux/riscv64        80cde017a105
    └─ linux/s390x          2b5b26e09ca2

The `TestTree` implementation is really quirky though, as it uses a `[][]string`,
which won't work well if we want to make it more generic (with an "unknown"
depth); probably needs some type defined that has an optional slice for child
rows.

Signed-off-by: Sebastiaan van Stijn <[email protected]>
thaJeztah added a commit to thaJeztah/cli that referenced this issue Oct 28, 2024
Nothing mergeable here, but this was me playing around; initially to see
if we could print the format such as suggested in docker#5560 (comment)

That output is shown in `TestTree`:

    IMAGE/TAGS ID                                    DISK USAGE          CONTENT SIZE        USED
    alpine:latest                                    beefdbd8a1da        13.6MB              4.09MB
    ├─ 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        0B                  0B
    └─ linux/s390x                                   2b5b26e09ca2        0B                  0B

    namespace/image                                  beefdbd8a1da        13.6MB              4.09MB
    ├─ namespace/image:1                             beefdbd8a1da        -                   -
    ├─ namespace/image:1.0                           beefdbd8a1da        -                   -
    ├─ namespace/image:1.0.0                         beefdbd8a1da        -                   -
    └─ namespace/image:latest                        beefdbd8a1da        -                   -
       ├─ 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        0B                  0B
       └─ linux/s390x                                2b5b26e09ca2        0B                  0B

    internal.example.com/namespace/image             beefdbd8a1da        13.6MB              4.09MB
    ├─ internal.example.com/namespace/image:1        beefdbd8a1da        -                   -
    ├─ internal.example.com/namespace/image:1.0      beefdbd8a1da        -                   -
    ├─ internal.example.com/namespace/image:1.0.0    beefdbd8a1da        -                   -
    └─ internal.example.com/namespace/image:latest   beefdbd8a1da        -                   -
       ├─ 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        0B                  0B
       └─ linux/s390x                                2b5b26e09ca2        0B                  0B

And `TestTreeNoTrunc` (non-truncated):

    IMAGE/TAGS ID                                    DISK USAGE                                                                CONTENT SIZE        USED
    alpine:latest                                    sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   13.6MB              4.09MB
    ├─ linux/amd64                                   sha256:33735bd63cf84d7e388d9f6d297d348c523c044410f553bd878c6d7829612735   0B                  0B
    ├─ linux/arm/v6                                  sha256:50f635c8b04d86dde8a02bcd8d667ba287eb8b318c1c0cf547e5a48ddadea1be   0B                  0B
    ├─ linux/arm/v7                                  sha256:f2f82d42495723c4dc508fd6b0978a5d7fe4efcca4282e7aae5e00bcf4057086   0B                  0B
    ├─ linux/arm64/v8                                sha256:9cee2b382fe2412cd77d5d437d15a93da8de373813621f2e4d406e3df0cf0e7c   13.6MB              4.09MB
    ├─ linux/386                                     sha256:b3e87f642f5c48cdc7556c3e03a0d63916bd0055ba6edba7773df3cb1a76f224   0B                  0B
    ├─ linux/ppc64le                                 sha256:c7a6800e3dc569a2d6e90627a2988f2a7339e6f111cdf6a0054ad1ff833e99b0   0B                  0B
    ├─ linux/riscv64                                 sha256:80cde017a10529a18a7274f70c687bb07c4969980ddfb35a1b921fda3a020e5b   0B                  0B
    └─ linux/s390x                                   sha256:2b5b26e09ca2856f50ac88312348d26c1ac4b8af1df9f580e5cf465fd76e3d4d   0B                  0B

    namespace/image                                  sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   13.6MB              4.09MB
    ├─ namespace/image:1                             sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   -                   -
    ├─ namespace/image:1.0                           sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   -                   -
    ├─ namespace/image:1.0.0                         sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   -                   -
    └─ namespace/image:latest                        sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   -                   -
       ├─ linux/amd64                                sha256:33735bd63cf84d7e388d9f6d297d348c523c044410f553bd878c6d7829612735   0B                  0B
       ├─ linux/arm/v6                               sha256:50f635c8b04d86dde8a02bcd8d667ba287eb8b318c1c0cf547e5a48ddadea1be   0B                  0B
       ├─ linux/arm/v7                               sha256:f2f82d42495723c4dc508fd6b0978a5d7fe4efcca4282e7aae5e00bcf4057086   0B                  0B
       ├─ linux/arm64/v8                             sha256:9cee2b382fe2412cd77d5d437d15a93da8de373813621f2e4d406e3df0cf0e7c   13.6MB              4.09MB
       ├─ linux/386                                  sha256:b3e87f642f5c48cdc7556c3e03a0d63916bd0055ba6edba7773df3cb1a76f224   0B                  0B
       ├─ linux/ppc64le                              sha256:c7a6800e3dc569a2d6e90627a2988f2a7339e6f111cdf6a0054ad1ff833e99b0   0B                  0B
       ├─ linux/riscv64                              sha256:80cde017a10529a18a7274f70c687bb07c4969980ddfb35a1b921fda3a020e5b   0B                  0B
       └─ linux/s390x                                sha256:2b5b26e09ca2856f50ac88312348d26c1ac4b8af1df9f580e5cf465fd76e3d4d   0B                  0B

    internal.example.com/namespace/image             sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   13.6MB              4.09MB
    ├─ internal.example.com/namespace/image:1        sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   -                   -
    ├─ internal.example.com/namespace/image:1.0      sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   -                   -
    ├─ internal.example.com/namespace/image:1.0.0    sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   -                   -
    └─ internal.example.com/namespace/image:latest   sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   -                   -
       ├─ linux/amd64                                sha256:33735bd63cf84d7e388d9f6d297d348c523c044410f553bd878c6d7829612735   0B                  0B
       ├─ linux/arm/v6                               sha256:50f635c8b04d86dde8a02bcd8d667ba287eb8b318c1c0cf547e5a48ddadea1be   0B                  0B
       ├─ linux/arm/v7                               sha256:f2f82d42495723c4dc508fd6b0978a5d7fe4efcca4282e7aae5e00bcf4057086   0B                  0B
       ├─ linux/arm64/v8                             sha256:9cee2b382fe2412cd77d5d437d15a93da8de373813621f2e4d406e3df0cf0e7c   13.6MB              4.09MB
       ├─ linux/386                                  sha256:b3e87f642f5c48cdc7556c3e03a0d63916bd0055ba6edba7773df3cb1a76f224   0B                  0B
       ├─ linux/ppc64le                              sha256:c7a6800e3dc569a2d6e90627a2988f2a7339e6f111cdf6a0054ad1ff833e99b0   0B                  0B
       ├─ linux/riscv64                              sha256:80cde017a10529a18a7274f70c687bb07c4969980ddfb35a1b921fda3a020e5b   0B                  0B
       └─ linux/s390x                                sha256:2b5b26e09ca2856f50ac88312348d26c1ac4b8af1df9f580e5cf465fd76e3d4d   0B                  0B

The above is all without the nice color-formatting etc, but this would be handled
before this;

The second bit was to see if we could make the tree output more align
with other output formats;

- Most of our commands allow passing a `--format`, including for (e.g.) `table`
- We want the tree view to also support, e.g. `--no-trunc`, which means that
  some columns will be wider.
- If we use a tabwriter for printing, we can have it handle the column-sizing
  for us.
- And if we do, we could let the user pass a custom format, and still print
  it as a tree.

e.g., a format could be;

    --format 'tree {.Image}}\t{{.Digest}}\t{{.InUse}}'

Which would output something like

    IMAGE                   ID             USED
    alpine:latest           beefdbd8a1da    ✔
    ├─ linux/amd64          33735bd63cf8
    ├─ linux/arm/v6         50f635c8b04d
    ├─ linux/arm/v7         f2f82d424957
    ├─ linux/arm64/v8       9cee2b382fe2    ✔
    ├─ linux/386            b3e87f642f5c
    ├─ linux/ppc64le        c7a6800e3dc5
    ├─ linux/riscv64        80cde017a105
    └─ linux/s390x          2b5b26e09ca2

The `TestTree` implementation is really quirky though, as it uses a `[][]string`,
which won't work well if we want to make it more generic (with an "unknown"
depth); probably needs some type defined that has an optional slice for child
rows; those child-rows can be pre-formatted.
thaJeztah added a commit to thaJeztah/cli that referenced this issue Oct 28, 2024
Nothing mergeable here, but this was me playing around; initially to see
if we could print the format such as suggested in docker#5560 (comment)

That output is shown in `TestTree`:

    IMAGE/TAGS ID                                    DISK USAGE          CONTENT SIZE        USED
    alpine:latest                                    beefdbd8a1da        13.6MB              4.09MB
    ├─ 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        0B                  0B
    └─ linux/s390x                                   2b5b26e09ca2        0B                  0B

    namespace/image                                  beefdbd8a1da        13.6MB              4.09MB
    ├─ namespace/image:1                             beefdbd8a1da        -                   -
    ├─ namespace/image:1.0                           beefdbd8a1da        -                   -
    ├─ namespace/image:1.0.0                         beefdbd8a1da        -                   -
    └─ namespace/image:latest                        beefdbd8a1da        -                   -
       ├─ 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        0B                  0B
       └─ linux/s390x                                2b5b26e09ca2        0B                  0B

    internal.example.com/namespace/image             beefdbd8a1da        13.6MB              4.09MB
    ├─ internal.example.com/namespace/image:1        beefdbd8a1da        -                   -
    ├─ internal.example.com/namespace/image:1.0      beefdbd8a1da        -                   -
    ├─ internal.example.com/namespace/image:1.0.0    beefdbd8a1da        -                   -
    └─ internal.example.com/namespace/image:latest   beefdbd8a1da        -                   -
       ├─ 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        0B                  0B
       └─ linux/s390x                                2b5b26e09ca2        0B                  0B

And `TestTreeNoTrunc` (non-truncated):

    IMAGE/TAGS ID                                    DISK USAGE                                                                CONTENT SIZE        USED
    alpine:latest                                    sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   13.6MB              4.09MB
    ├─ linux/amd64                                   sha256:33735bd63cf84d7e388d9f6d297d348c523c044410f553bd878c6d7829612735   0B                  0B
    ├─ linux/arm/v6                                  sha256:50f635c8b04d86dde8a02bcd8d667ba287eb8b318c1c0cf547e5a48ddadea1be   0B                  0B
    ├─ linux/arm/v7                                  sha256:f2f82d42495723c4dc508fd6b0978a5d7fe4efcca4282e7aae5e00bcf4057086   0B                  0B
    ├─ linux/arm64/v8                                sha256:9cee2b382fe2412cd77d5d437d15a93da8de373813621f2e4d406e3df0cf0e7c   13.6MB              4.09MB
    ├─ linux/386                                     sha256:b3e87f642f5c48cdc7556c3e03a0d63916bd0055ba6edba7773df3cb1a76f224   0B                  0B
    ├─ linux/ppc64le                                 sha256:c7a6800e3dc569a2d6e90627a2988f2a7339e6f111cdf6a0054ad1ff833e99b0   0B                  0B
    ├─ linux/riscv64                                 sha256:80cde017a10529a18a7274f70c687bb07c4969980ddfb35a1b921fda3a020e5b   0B                  0B
    └─ linux/s390x                                   sha256:2b5b26e09ca2856f50ac88312348d26c1ac4b8af1df9f580e5cf465fd76e3d4d   0B                  0B

    namespace/image                                  sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   13.6MB              4.09MB
    ├─ namespace/image:1                             sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   -                   -
    ├─ namespace/image:1.0                           sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   -                   -
    ├─ namespace/image:1.0.0                         sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   -                   -
    └─ namespace/image:latest                        sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   -                   -
       ├─ linux/amd64                                sha256:33735bd63cf84d7e388d9f6d297d348c523c044410f553bd878c6d7829612735   0B                  0B
       ├─ linux/arm/v6                               sha256:50f635c8b04d86dde8a02bcd8d667ba287eb8b318c1c0cf547e5a48ddadea1be   0B                  0B
       ├─ linux/arm/v7                               sha256:f2f82d42495723c4dc508fd6b0978a5d7fe4efcca4282e7aae5e00bcf4057086   0B                  0B
       ├─ linux/arm64/v8                             sha256:9cee2b382fe2412cd77d5d437d15a93da8de373813621f2e4d406e3df0cf0e7c   13.6MB              4.09MB
       ├─ linux/386                                  sha256:b3e87f642f5c48cdc7556c3e03a0d63916bd0055ba6edba7773df3cb1a76f224   0B                  0B
       ├─ linux/ppc64le                              sha256:c7a6800e3dc569a2d6e90627a2988f2a7339e6f111cdf6a0054ad1ff833e99b0   0B                  0B
       ├─ linux/riscv64                              sha256:80cde017a10529a18a7274f70c687bb07c4969980ddfb35a1b921fda3a020e5b   0B                  0B
       └─ linux/s390x                                sha256:2b5b26e09ca2856f50ac88312348d26c1ac4b8af1df9f580e5cf465fd76e3d4d   0B                  0B

    internal.example.com/namespace/image             sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   13.6MB              4.09MB
    ├─ internal.example.com/namespace/image:1        sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   -                   -
    ├─ internal.example.com/namespace/image:1.0      sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   -                   -
    ├─ internal.example.com/namespace/image:1.0.0    sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   -                   -
    └─ internal.example.com/namespace/image:latest   sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d   -                   -
       ├─ linux/amd64                                sha256:33735bd63cf84d7e388d9f6d297d348c523c044410f553bd878c6d7829612735   0B                  0B
       ├─ linux/arm/v6                               sha256:50f635c8b04d86dde8a02bcd8d667ba287eb8b318c1c0cf547e5a48ddadea1be   0B                  0B
       ├─ linux/arm/v7                               sha256:f2f82d42495723c4dc508fd6b0978a5d7fe4efcca4282e7aae5e00bcf4057086   0B                  0B
       ├─ linux/arm64/v8                             sha256:9cee2b382fe2412cd77d5d437d15a93da8de373813621f2e4d406e3df0cf0e7c   13.6MB              4.09MB
       ├─ linux/386                                  sha256:b3e87f642f5c48cdc7556c3e03a0d63916bd0055ba6edba7773df3cb1a76f224   0B                  0B
       ├─ linux/ppc64le                              sha256:c7a6800e3dc569a2d6e90627a2988f2a7339e6f111cdf6a0054ad1ff833e99b0   0B                  0B
       ├─ linux/riscv64                              sha256:80cde017a10529a18a7274f70c687bb07c4969980ddfb35a1b921fda3a020e5b   0B                  0B
       └─ linux/s390x                                sha256:2b5b26e09ca2856f50ac88312348d26c1ac4b8af1df9f580e5cf465fd76e3d4d   0B                  0B

The above is all without the nice color-formatting etc, but this would be handled
before this;

The second bit was to see if we could make the tree output more align
with other output formats;

- Most of our commands allow passing a `--format`, including for (e.g.) `table`
- We want the tree view to also support, e.g. `--no-trunc`, which means that
  some columns will be wider.
- If we use a tabwriter for printing, we can have it handle the column-sizing
  for us.
- And if we do, we could let the user pass a custom format, and still print
  it as a tree.

e.g., a format could be;

    --format 'tree {.Image}}\t{{.Digest}}\t{{.InUse}}'

Which would output something like

    IMAGE                   ID             USED
    alpine:latest           beefdbd8a1da    ✔
    ├─ linux/amd64          33735bd63cf8
    ├─ linux/arm/v6         50f635c8b04d
    ├─ linux/arm/v7         f2f82d424957
    ├─ linux/arm64/v8       9cee2b382fe2    ✔
    ├─ linux/386            b3e87f642f5c
    ├─ linux/ppc64le        c7a6800e3dc5
    ├─ linux/riscv64        80cde017a105
    └─ linux/s390x          2b5b26e09ca2

The `TestTree` implementation is really quirky though, as it uses a `[][]string`,
which won't work well if we want to make it more generic (with an "unknown"
depth); probably needs some type defined that has an optional slice for child
rows; those child-rows can be pre-formatted.

Signed-off-by: Sebastiaan van Stijn <[email protected]>
@laurazard
Copy link
Member

laurazard commented Oct 28, 2024

IMO neither of the "Split per repository"

$ docker image ls --tree
IMAGE                                            ID             DISK USAGE   CONTENT SIZE   USED
alpine:latest                                    beefdbd8a1da       13.6MB         4.09MB
├─ 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           0B             0B
└─ linux/s390x                                   2b5b26e09ca2           0B             0B

namespace/image:1
namespace/image:1.0
namespace/image:1.0.0
namespace/image:latest
namespace/image:latest                           beefdbd8a1da       13.6MB         4.09MB
├─ 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           0B             0B
└─ linux/s390x                                   2b5b26e09ca2           0B             0B

internal.example.com/namespace/image:1
internal.example.com/namespace/image:1.0
internal.example.com/namespace/image:1.0.0
internal.example.com/namespace/image:latest      beefdbd8a1da       13.6MB         4.09MB
├─ 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           0B             0B
└─ linux/s390x                                   2b5b26e09ca2           0B             0B

or "Tree per repository"

$ docker image ls --tree
IMAGE/TAGS                                       ID             DISK USAGE   CONTENT SIZE   USED
alpine:latest                                    beefdbd8a1da       13.6MB         4.09MB
├─ 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           0B             0B
└─ linux/s390x                                   2b5b26e09ca2           0B             0B


namespace/image                                  beefdbd8a1da       13.6MB         4.09MB
├─ namespace/image:1                             beefdbd8a1da            -              -
├─ namespace/image:1.0                           beefdbd8a1da            -              -
├─ namespace/image:1.0.0                         beefdbd8a1da            -              -
└─ namespace/image:latest                        beefdbd8a1da            -              -
   ├─ 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           0B             0B
   └─ linux/s390x                                2b5b26e09ca2           0B             0B

internal.example.com/namespace/image             beefdbd8a1da       13.6MB         4.09MB
├─ internal.example.com/namespace/image:1        beefdbd8a1da            -              -
├─ internal.example.com/namespace/image:1.0      beefdbd8a1da            -              -
├─ internal.example.com/namespace/image:1.0.0    beefdbd8a1da            -              -
└─ internal.example.com/namespace/image:latest   beefdbd8a1da            -              -
   ├─ 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           0B             0B
   └─ linux/s390x                                2b5b26e09ca2           0B             0B

are good options – there's no visual indication that these are all actually the same image, and an unsuspecting user (or me, if I wasn't paying close attention) would quickly glance here and presume that I have three different images stored rather than one image with a number of different tags.

Particularly for the "tree per repository" option, I think the output quickly becomes unintelligibly long. Consider

$ docker image ls --tree
IMAGE/TAGS                                             ID             DISK USAGE   CONTENT SIZE   USED
namespace/image                                        beefdbd8a1da       13.6MB         4.09MB
├─ namespace/image:1                                   beefdbd8a1da            -              -
├─ namespace/image:1.0                                 beefdbd8a1da            -              -
├─ namespace/image:1.0.0                               beefdbd8a1da            -              -
└─ namespace/image:latest                              beefdbd8a1da            -              -
   ├─ 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           0B             0B
   └─ linux/s390x                                      2b5b26e09ca2           0B             0B

internal.example.com/namespace/image                   beefdbd8a1da       13.6MB         4.09MB
├─ internal.example.com/namespace/image:1              beefdbd8a1da            -              -
├─ internal.example.com/namespace/image:1.0            beefdbd8a1da            -              -
├─ internal.example.com/namespace/image:1.0.0          beefdbd8a1da            -              -
└─ internal.example.com/namespace/image:latest         beefdbd8a1da            -              -
   ├─ 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           0B             0B
   └─ linux/s390x                                      2b5b26e09ca2           0B             0B

namespace/other-image                                  768e5c6f5cb6       13.6MB         4.09MB
├─ namespace/other-image:1                             768e5c6f5cb6            -              -
├─ namespace/other-image:1.0                           768e5c6f5cb6            -              -
├─ namespace/other-image:1.0.0                         768e5c6f5cb6            -              -
└─ namespace/other-image:latest                        768e5c6f5cb6            -              -
   ├─ linux/amd64                                      7615936bd840           0B             0B
   ├─ linux/arm/v6                                     22f27168517d           0B             0B
   ├─ linux/arm/v7                                     dc3bab2a4285           0B             0B
   ├─ linux/arm64/v8                                   a9fc789b4096       13.6MB         4.09MB
   ├─ linux/386                                        98c3f7257909           0B             0B
   ├─ linux/ppc64le                                    a4683230268f           0B             0B
   ├─ linux/riscv64                                    0e1d386b0b5d           0B             0B
   └─ linux/s390x                                      b129ffc84b55           0B             0B

internal.example.com/namespace/other-image             768e5c6f5cb6       13.6MB         4.09MB
├─ internal.example.com/namespace/other-image:1        768e5c6f5cb6            -              -
├─ internal.example.com/namespace/other-image:1.0      768e5c6f5cb6            -              -
├─ internal.example.com/namespace/other-image:1.0.0    768e5c6f5cb6            -              -
└─ internal.example.com/namespace/other-image:latest   768e5c6f5cb6            -              -
   ├─ linux/amd64                                      7615936bd840           0B             0B
   ├─ linux/arm/v6                                     22f27168517d           0B             0B
   ├─ linux/arm/v7                                     dc3bab2a4285           0B             0B
   ├─ linux/arm64/v8                                   a9fc789b4096       13.6MB         4.09MB
   ├─ linux/386                                        98c3f7257909           0B             0B
   ├─ linux/ppc64le                                    a4683230268f           0B             0B
   ├─ linux/riscv64                                    0e1d386b0b5d           0B             0B
   └─ linux/s390x                                      b129ffc84b55           0B             0B

I only have two indexes in that output, but it's more than double as tall as my console normally is.

@thaJeztah
Copy link
Member Author

thaJeztah commented Oct 28, 2024

Right, but consider if those would all be a single manifest, then the current view for the above would look like;

$ docker image ls --tree
IMAGE/TAGS                                             ID             DISK USAGE   CONTENT SIZE   USED
namespace/image:1
namespace/image:1.0
namespace/image:1.0.0
namespace/image:latest
internal.example.com/namespace/image:1
internal.example.com/namespace/image:1.0
internal.example.com/namespace/image:1.0.0
internal.example.com/namespace/image:latest
namespace/other-image:1
namespace/other-image:1.0
namespace/other-image:1.0.0
namespace/other-image:latest
internal.example.com/namespace/other-image:1
internal.example.com/namespace/other-image:1.0
internal.example.com/namespace/other-image:1.0.0
internal.example.com/namespace/other-image:latest   768e5c6f5cb6       13.6MB         4.09MB
├─ linux/amd64                                      7615936bd840           0B             0B
├─ linux/arm/v6                                     22f27168517d           0B             0B
├─ linux/arm/v7                                     dc3bab2a4285           0B             0B
├─ linux/arm64/v8                                   a9fc789b4096       13.6MB         4.09MB
├─ linux/386                                        98c3f7257909           0B             0B
├─ linux/ppc64le                                    a4683230268f           0B             0B
├─ linux/riscv64                                    0e1d386b0b5d           0B             0B
└─ linux/s390x                                      b129ffc84b55           0B             0B

@vvoland
Copy link
Collaborator

vvoland commented Oct 28, 2024

I don't think that's worse than the proposed alternatives 🙈

But I guess we could make the grouping configurable, so we can all be happy? 😅

@laurazard
Copy link
Member

laurazard commented Oct 28, 2024

$ docker image ls --tree
IMAGE/TAGS                                             ID             DISK USAGE   CONTENT SIZE   USED
namespace/image:1
namespace/image:1.0
namespace/image:1.0.0
namespace/image:latest
internal.example.com/namespace/image:1
internal.example.com/namespace/image:1.0
internal.example.com/namespace/image:1.0.0
internal.example.com/namespace/image:latest
namespace/other-image:1
namespace/other-image:1.0
namespace/other-image:1.0.0
namespace/other-image:latest
internal.example.com/namespace/other-image:1
internal.example.com/namespace/other-image:1.0
internal.example.com/namespace/other-image:1.0.0
internal.example.com/namespace/other-image:latest   768e5c6f5cb6       13.6MB         4.09MB
├─ linux/amd64                                      7615936bd840           0B             0B
├─ linux/arm/v6                                     22f27168517d           0B             0B
├─ linux/arm/v7                                     dc3bab2a4285           0B             0B
├─ linux/arm64/v8                                   a9fc789b4096       13.6MB         4.09MB
├─ linux/386                                        98c3f7257909           0B             0B
├─ linux/ppc64le                                    a4683230268f           0B             0B
├─ linux/riscv64                                    0e1d386b0b5d           0B             0B
└─ linux/s390x                                      b129ffc84b55           0B             0B

IMO that's a bit better than the other case – sure, it's not as "pretty" but it makes it clear it's all the same image and ultimately uses less space/I can see most of that in a console the size I normally use.

@thaJeztah
Copy link
Member Author

but it makes it clear it's all the same image

So that's the bit I'm really not sure about. How much should we consider them the same image ? There's many scenarios where they are not the same, and where we actually want to track / manage them separate;

  • e.g., if I pushed internal.example.com/namespace/other-image:1, but didn't push namespace/other-image:1
  • my company may have RAM, in which case I may be allowed to use namespace/other-image:1, but not allowed to use internal.example.com/namespace/other-image:1

There's just too many scenarios where, even though they may be sharing the same content under the hood, they are separate things to manage.

I do agree about the verbosity (output can get lengthy), which is why we could consider having the tree output default to "only show what's present";

$ docker image ls --tree

IMAGE/TAGS                                       ID             DISK USAGE   CONTENT SIZE   USED
alpine:latest                                    beefdbd8a1da       13.6MB         4.09MB
└─ linux/arm64/v8                                9cee2b382fe2       13.6MB         4.09MB

namespace/image                                  beefdbd8a1da       13.6MB         4.09MB
├─ namespace/image:1                             beefdbd8a1da            -              -
├─ namespace/image:1.0                           beefdbd8a1da            -              -
├─ namespace/image:1.0.0                         beefdbd8a1da            -              -
└─ namespace/image:latest                        beefdbd8a1da            -              -
   └─ linux/arm64/v8                             9cee2b382fe2       13.6MB         4.09MB

Grouping by namespace/image (with the same digest) could make management easier when combined with;

In that case, things like this could be an option;

# push all the tags for the same image
$ docker push --all-tags namespace/image:1

# remove all the tags
$ docker image rm --all-tags namespace/image:1

@laurazard
Copy link
Member

e.g., if I pushed internal.example.com/namespace/other-image:1, but didn't push namespace/other-image:1
my company may have RAM, in which case I may be allowed to use namespace/other-image:1, but not allowed to use internal.example.com/namespace/other-image:1

That's definitely a tough question. IMO the "instinctive" model I have for this is, whether you say Laura or laurazard or some nickname, it's all referring to the same person. On the other hand, what you say about RAM and other cases is true. I'd generally be tempted to say that these are still the same image, you just can't pull it from some repo or push it to some repo, but I definitely see your perspective.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/ux containerd-integration Issues and PRs related to containerd integration kind/enhancement
Projects
None yet
Development

No branches or pull requests

3 participants