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
UX: improve / design UX for multi-arch images #44582
Comments
While swarm replicas are expected to be eventually completely fulfilled, platforms are not, so this may cause confusion. |
Yes, I definitely wasn't sold on that one myself, but thought I'd include it, to see if we think there's a need to show that an image is "partial" / "shallow" in some way. Not sure what the best, non-confusing presentation is for it (I ran a bit out of steam, so will give it further thinking as well, but ideas always welcome!) |
For listing images I quite like what @AkihiroSuda did i.e. one line per platform and we show the index digest and the image platform $ nerdctl images
REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE
alpine 3.16 b95359c25051 15 seconds ago linux/amd64 5.9 MiB 2.7 MiB
alpine 3.16 b95359c25051 15 seconds ago linux/arm64/v8 0.0 B 2.6 MiB I'm really not a fan of |
Sorry, I meant to come back to this much sooner 😩 I think we do need to do something with the image index here, because that's the actual top-level object we pull and reference by tag, and the images inside it are only indirectly tagged, so I think it's going to be even more confusing for users how those objects are structured in a registry if we hide it in the CLI experience. In other words, I think we'd provide the most value to our users if we show the tag attached to the top-level index object (which is the thing that's actually tagged in the containerd image store and the registry), and use something like one of the tree views that @thaJeztah suggested in order to show the per-architecture images we actually have locally (although I don't think we have to hide it behind a "verbose" flag, since the added detail about which ones I have locally is useful and important data that's critical to my understanding of what I have locally, which is the primary reason to run |
Multi-arch images Exploration-ProposalDescription:We are exploring a new default visualization that provides more advantages for the user like:
Actual statusRight now, this is the output for New default for
|
I quite like this proposal. The only think I'd like to push back on is a In any case, the hints are interesting and could benefit a lot of other areas in the CLI UX, but I think we should split discussion of those out of this initial proposal as they're really quite generic/not directly part of the scope of this issue. |
Yes I agree the "--hint" is okay for a separate discussion; it's something Javier was exploring; and probably something which (if we were to implement it) should be configurable globally (in config file?).we were discussing whether to remove it from the screenshots at this stage, but I suggested to keep it in for now, so that we can discuss some of the options we were exploring. In general; for the "not meant to be parseable" output(s) such as the tree presentation, the hints are likely okay; for other output likely "less desirable", but should be configurable either way (can be useful for beginning users, but once you are familiar with using docker, it becomes "just noise")
|
I don't like mixing image name and platform (like in |
Agree, also with that approach, and we avoid the collision of two Should we explore other ways? For example:
If we use one space, we cannot use the behavior of double-clicking one string and copying it. |
Thanks @tianon! Heh, yes, I was hoping to get some comments on that format. Let me put it in context; Javier was not yet familiar with all the concepts of OCI, Multi-Arch (manifest lists) etc. So, while I had to give a bit of a "bootcamp", I also tried to take advantage of his "not yet poisoned by domain knowledge" fresh eyes 👀 While we were discussing initial concepts, we also went through "multiple namespaces" (while not really seen much, and not supported by Docker Hub) are allowed ( However, while discussing; Javier asked some really good questions;
Besides "getting an overview of what's there", my answer after that was "... and then to select an image to interact with" (which could be "to inspect the image", "to delete the image", or "to run the image". Then the question became "how do you do that?". You need something unique to select that image. The current output of
In short;
So, while the example may not be perfect, we decided "let's include it", and take it as a starting point to discuss if we could come up with such a format. |
Oh! I see @jalonsogo also replied while I was fighting the tiny keys on my phone to write down my reply 😂❤️❤️ |
Yeah, I 100% love the (I had to wait until I was reasonably confident that I'd ported the majority of my really old scripts from $ jq -r .imagesFormat .docker/config.json
table {{ $haveRepo := ne .Repository "<none>" }}{{ $haveTag := ne .Tag "<none>" }}{{ $haveDigest := and (ne .Digest "<none>") (ne .Digest "") }}{{ if and $haveRepo (or $haveTag $haveDigest) }}{{ .Repository }}{{ if $haveTag }}:{{ .Tag }}{{ else }}@{{.Digest}}{{ end }}{{ else }}{{ if $haveRepo }}{{ .Repository }} @ ... <use --digests>{{ else }}...{{ end }}{{ end }}\t{{ .ID }}\t{{ .CreatedSince }}\t{{ .Size }}
$ docker images debian
REPOSITORY:TAG IMAGE ID CREATED SIZE
debian:bullseye-slim 224855429754 9 days ago 80.5MB Like you, I use the default output primarily for seeing what I have locally (size, age, specific tags, dangling images) and for copy-pasting into other tools. In the containerd integration, an additional very related thing I expect to be able to see from this is which specific platforms I've pulled locally for each image, so IMO we're on the right track. Using any character that directly connects the image name and the architecture makes me nervous because it looks like syntax, and I'm more likely to expect it to be something I can pass into tools somehow/somewhere (if Docker presents the information in this format, it must be the format Docker wants to accept as well). I really like the idea of very explicitly separating the "visual" use case from the "scraping" use case, and think it would be totally fair to have a much more dense display (like a dedicated "platform" column) specifically for scraping. Honestly I don't ever use |
One thing I realized today while talking to @yosifkit about this is that with the c8d content store, "image ID" is a lot less relevant in the general case than it used to be -- for images with a tag, that's usually what we want, but for images without a tag (either pull-by-digest or dangling), the image ID is the digest, so would already be implied/included. |
Description
relates to:
With the containerd-integration in progress, we need to decide on UX for managing multi-arch images. Where previously an image would always be a single architecture, images may now be multi-arch, and we store multiple architectures / variants of an image. We discussed this topic some weeks agon in the containerd sync call, and the proposal was to create a ticket for discussion. Since that call, PR rumpl#113 made some changes (not yet upstreamed) to show individual architectures as individual images, which helps with visualising that the local image store has multiple variants stored for an image (and somewhat matches
nerdctl
), however, as we currently don't present the image's architecture in overview, this presentation is not ideal. It may also be a bit disjoint from the concept of multi-arch images, as image-variants now become "separate", somewhat defeating the concept of "multi".This ticket describes some options; none of these are decided on (or final for that matter), but hopefully this can act as a starting point to come to a concensus on UX.
Assumptions
While writing these options, I made the following assumptions:
docker image rm alpine:3.16
, I just want to removealpine:3.16
)Listing images
We need to decide where (and when) to expose architectures. We had some discussion about this during one of the maintainers calls, when discussing #42464. At the time, the question was raised "should this be visible by default?". There may not be a single answer to this (different scenarios require different information), and we could decide to include the platform information in API responses, but don't print the information by default.
If we decide to not include the platform, the output of
docker images
would remain the same as before multi-arch. Each image represents an image-manifest (either single- or multi-arch);As we are showing manifest index (for multi-arch), we can add a
PLATFORMS
templating placeholder. Users can either use their own template, or we can add a flag to show that column. The column would show the variants that are present in the image cache (store) to keep the list short (and of we would truncate the output by default, unless--no-trunc
is set). TheSIZE
column showing the size of all variants currently stored;Shallow / non-shallow pulls
There's some ambiguity, because
alpine:3.16
is a multi-arch image, and provides many architectures. In the example above,alpine:3.16
is effectively a "shallow" pull; not all of the variants have been pulled (which is the most likely scenario). For reference, this is the list from Docker Hub; https://hub.docker.com/_/alpine/tags?page=1&name=3.16.3For cases where the user needs to interact with individual variants of the image, we can;
--verbose
or--show-platforms
flag--platform
flag on commands such asdocker image rm
/docker rmi
, anddocker image inspect
to provide more granular control.We can use something similar to
docker service ps
;Which could look something like this:
It's worth noting that manifest (lists) are not necessarily unique; multiple tags can resolve to the same manifest(list). For example, if both
alpine:latest
andalpine:3.16
would have resolved to the same digest, the detailed list would be like below:Note that in this case showing the
REPOSITORY
andTAG
for each variant therefore is not "strictly correct", as those variants are not directly associated with aREPO
orTAG
. It's also not possible to "untag" such references (as this would mean "remove a reference from the manifest list", which would mean "create a new image manifest"). Because of this, we may want to consider to not present theTAG
(and perhaps evenREPOSITORY
) for the variants;Removing the
REPOSITORY
is a bit awkward, as it's the first column; we could consider changing the order of columns, putting the ID (digest) first;Given that in this presentation the columns don't align either way, we could consider omitting
PLATFORMS
for the top-level, re-purposing the space belowREPOSITORY
andTAG
;Inspecting images
With the individual variants broken up, users can remove (or inspect) individual variants of an image, for example, to inspect the
linux/s390x
variant of the alpine image:For convenience, we should consider adding
--platform
to filter / show a specific variant:docker image inspect
defaults to showing the image for the default platform.Doing so would improve visibility for multi-arch images. The output of
docker image inspect
is already an array (which is used when inspecting multiple images);Deleting images
Similarly to
docker image inspect
, the digest can be used to delete individual variants;Note that this will remove the variant, so it should disappear from both
alpine:3.16
andalpine:latest
(or any image referencing it):As an alternative, we can add a
--platform
flag todocker image rm
as well; the command below would achieve the same as above;❓ what do we want the behavior to be if (as in the example) the variant is referenced by multiple architectures? The
docker image rm --platform
command is ambiguous, as the user request the variant to be removed from thealpine:3.16
image. It may be surprising that it's also removed from thealpine:latest
image (I guess the "most correct" presentation would be to show one line per digest, and multiple tags after it, but this is a HUGE change, and may not be very user-friendly).Shallow, shallower, shallowest
As images in the local store may be a "shallow" pull of a multi-arch image, the question is: do we want to provide insight into that? If so, how?
docker image pull
without specifying a--platform
?For the "how much is missing comparing to (e.g.)
docker service ls
;We could add (optional) columns for "counts" to see "how" shallow the image is;
For the "verbose" output, we could consider having an option to show what's missing; not sure (yet) how to best present that it's "missing", perhaps the
SIZE
column to show how much is there, or aMISSING
somewhere?Filtering
Add a
--platform
option todocker image ls
(and consider a--filter platform=xxx
). Using the filter would show any image that currently has the given os/arch present;In "verbose" view, this would hide the other architectures;
Pruning
To be discussed; do we want pruning to default to
--all
is set, do 1., otherwise do 2.Pulling images
If an image is not present in the local store, the current behavior is to pull with the default platform (platform of the host).
We need to define the expected behavior when pulling an image that is already present.
what should happen when
docker image pull
without specifying a--platform
?docker image pull
with an explicit--platform=<DEFAULT PLATFORM>
docker image pull
with--platform=<other platform>
docker run --platform
and the given platform is not in the current imageCurrently, the behavior is confusing (and there's some bugs / undefined behavior);
The part to define if image should be updated (re-resolving the digest) or not. There's advantages to either, but equally "confusing" behavior.
It depends on what we envision
pull
to mean, and whether a--platform
was specified (explicitly?). The changes are subtle, but may be important. Some options;name:tag
), irregardless of--platform
to be specified (explicitly), we resolve the digest, and pull the image.--platform
specified--platform
specified2.
as default, but offer a--resolve
,--update
or--pull=<some option>
option to force updating.--platform
specified, then--platform
specified, thenMy preference goes out to
2.
or4.
when a--platform
is set, as it doesn't implicitly update the image for other architectures.5.
for when no--platform
is set; this is the closes match to the "pre-multi-arch" behavior: when pulling an image, it's updated to the latest version. But with multi-arch, this means "all arches that I already have".The text was updated successfully, but these errors were encountered: