Skip to content

fix(image): don't treat digest-only images as dangling in list output#6960

Open
mohithshuka wants to merge 6 commits intodocker:masterfrom
mohithshuka:fix/docker-images-readable-output
Open

fix(image): don't treat digest-only images as dangling in list output#6960
mohithshuka wants to merge 6 commits intodocker:masterfrom
mohithshuka:fix/docker-images-readable-output

Conversation

@mohithshuka
Copy link
Copy Markdown

Problem

docker images was hiding images that have a digest but no tag, treating
them as dangling. This caused valid images to silently disappear from
default output.

The local isDangling function in list.go was missing the
len(img.RepoDigests) == 0 check, so any image with no tags but a valid
digest was incorrectly filtered out.

Fix

Align list.go's isDangling with the definition already correct in
formatter/image.go — an image is only dangling if it has both no tags
AND no digests.

Before / After

Before: Images with digest but no tag silently hidden from docker images
After: Those images appear in output as expected

Fixes #6650

mohithshuka and others added 6 commits April 9, 2026 17:45
Fixes #24643

--kernel-memory was deprecated in v20.10 and removed in v23.0.
Add deprecation callouts to both the options table and the
Kernel memory constraints section of the run reference page.
The --filter flag for 'docker volume prune' previously only showed
'label=<label>' as an example, not mentioning the negation form
'label!=<label>', even though it is valid and supported by the daemon.

Fixes docker#6918

Signed-off-by: mohithshuka <153504854+mohithshuka@users.noreply.github.com>
When a port is bound on both 0.0.0.0 and ::, hide the IPv6 entry
and show only the IPv4 entry to reduce noise in docker ps output.

Before: 0.0.0.0:8080->80/tcp, :::8080->80/tcp
After:  0.0.0.0:8080->80/tcp

Fixes docker#6869
The --archive (-a) flag description was misleading. Updated to clarify
that it preserves uid/gid from the source, and that it only takes
effect when copying files TO a container (not from).

Fixes docker#6870
Signed-off-by: mohithshuka <153504854+mohithshuka@users.noreply.github.com>
The local isDangling in list.go was missing the RepoDigests check,
causing images with a digest but no tag to be incorrectly filtered
from default 'docker images' output. Align with formatter.isDangling.

Fixes docker#6650
Copilot AI review requested due to automatic review settings April 29, 2026 13:14
@mohithshuka mohithshuka requested review from a team and thaJeztah as code owners April 29, 2026 13:14
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes incorrect filtering in docker images so digest-only images are not treated as dangling (and therefore not hidden), alongside several CLI help/doc updates and a docker ps port-formatting tweak.

Changes:

  • Fix cli/command/image/list.go dangling detection to require both no tags and no digests.
  • Adjust docker ps port rendering to suppress duplicate IPv6 wildcard entries when an equivalent IPv4 wildcard mapping exists.
  • Update CLI help text and docs for docker cp --archive, docker run --kernel-memory deprecation, and volume prune filter examples.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
docs/reference/run.md Marks --kernel-memory as deprecated/removed and adds a deprecation callout in the kernel memory section.
docs/reference/commandline/cp.md Updates generated docs text for docker cp --archive behavior.
docs/reference/commandline/container_cp.md Updates generated docs text for docker container cp --archive behavior.
cli/command/volume/prune.go Expands --filter help example to include label!=....
cli/command/image/list.go Fixes dangling filtering so digest-only images aren’t removed from default docker images output.
cli/command/formatter/container.go Suppresses duplicate IPv6 wildcard port mappings in DisplayablePorts.
cli/command/container/cp.go Updates --archive flag help text to clarify behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +368 to +384
// Pre-pass: record which (hostPort, privatePort, proto) tuples have an
// IPv4 wildcard (0.0.0.0) binding. Used below to suppress the matching
// IPv6 wildcard (::) entry, avoiding duplicate output such as:
// 0.0.0.0:8080->80/tcp, :::8080->80/tcp
// See: https://github.com/docker/cli/issues/6869
type mappingKey struct {
hostPort uint16
privatePort uint16
proto string
}
ipv4Bindings := make(map[mappingKey]bool)
for _, port := range ports {
if port.IP.String() == "0.0.0.0" && port.PublicPort != 0 {
ipv4Bindings[mappingKey{port.PublicPort, port.PrivatePort, port.Type}] = true
}
}

Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR title/description focus on fixing docker images filtering of digest-only images, but this PR also includes unrelated changes (port formatting suppression in DisplayablePorts, docs updates for --kernel-memory, docker cp flag text, and volume prune filter help). Please either split these into separate PRs or update the PR title/description to accurately describe the full scope, to make review and release notes clearer.

Copilot uses AI. Check for mistakes.
Comment on lines +368 to +372
// Pre-pass: record which (hostPort, privatePort, proto) tuples have an
// IPv4 wildcard (0.0.0.0) binding. Used below to suppress the matching
// IPv6 wildcard (::) entry, avoiding duplicate output such as:
// 0.0.0.0:8080->80/tcp, :::8080->80/tcp
// See: https://github.com/docker/cli/issues/6869
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The newly added comment examples show IPv6 wildcard bindings as :::8080->80/tcp, but the actual formatting produced here uses net.JoinHostPort, which renders IPv6 as [::]:8080->80/tcp (see existing tests expecting [::1]:...). Please update the examples so they match real output and avoid confusion when reading this code.

Copilot uses AI. Check for mistakes.
Comment on lines 368 to +405
@@ -373,6 +391,18 @@ func DisplayablePorts(ports []container.PortSummary) string {
portKey := port.Type
if port.IP.IsValid() {
if port.PublicPort != current {
// Suppress the IPv6 wildcard entry when an IPv4 wildcard
// entry already covers the same (hostPort, privatePort, proto)
// tuple. This merges:
// 0.0.0.0:8080->80/tcp, :::8080->80/tcp
// into the cleaner:
// 0.0.0.0:8080->80/tcp
if port.IP.Is6() && !port.IP.Is4In6() && port.IP.IsUnspecified() {
key := mappingKey{port.PublicPort, port.PrivatePort, port.Type}
if ipv4Bindings[key] {
continue
}
}
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change introduces new behavior (suppressing the IPv6 wildcard :: mapping when an equivalent IPv4 wildcard 0.0.0.0 mapping exists), but there is no test coverage for the duplicate-output case (e.g., 0.0.0.0:8080->80/tcp + [::]:8080->80/tcp). Please add/extend a TestDisplayablePorts case to lock in the intended suppression behavior and prevent regressions.

Copilot uses AI. Check for mistakes.
Comment thread cli/command/image/list.go
Comment on lines +179 to 182
if len(img.RepoTags) == 0 && len(img.RepoDigests) == 0 {
return true
}
return len(img.RepoTags) == 1 && img.RepoTags[0] == "<none>:<none>" && len(img.RepoDigests) == 1 && img.RepoDigests[0] == "<none>@<none>"
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR changes the CLI-side dangling filtering so digest-only images are no longer removed from default docker images output. There are existing tests/goldens in cli/command/image/list_test.go (e.g., list-command-filter-dangling.no-dangling-filter.golden) that currently expect digest-only images to be hidden; those fixtures should be updated so the tests reflect the corrected behavior (digest-only images should remain visible when --all is not set and dangling filter is absent/false).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The new `docker images' output format is pretty unusable

2 participants