fix(image): pin the image a container runs to its digest - #5125
Open
ekalinin wants to merge 1 commit into
Open
Conversation
`nerdctl images` marks an image as in use by resolving the image name stored on the container, which follows the tag wherever it points now. After `nerdctl tag` moves a tag onto another image, the container gets attributed to an image it never ran: the U indicator lands on the wrong row. Record the image target digest on the container at creation time, in a new nerdctl/image-digest label, and use it for the in-use lookup. Containers created before this label existed, or created outside nerdctl, are still resolved by name; an unparsable value falls back the same way rather than dropping the container from the set. This also matters for the ACTIVE and RECLAIMABLE columns of `nerdctl system df`, which build on the same lookup. Signed-off-by: Eugene Kalinin <e.v.kalinin@gmail.com>
ekalinin
force-pushed
the
fix/image-in-use-digest
branch
from
August 6, 2026 12:46
3a458da to
a31ddac
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
nerdctl imagesmarks an image as in use by resolving the image name recorded on the container. A name is a mutable reference:container.Image(ctx)looks it up in the image store as it is now, not as it was when the container was created. Once a tag is moved, theUindicator lands on the wrong row.Both answers are wrong. The container still runs alpine, containerd still holds its snapshot and its layers, so alpine cannot be removed - yet it is shown as free, while nginx is shown as busy although nothing ever ran it. A container whose tag was removed altogether fails to resolve and drops out of the in-use set entirely.
The fix
Record the image target digest on the container at creation time, in a new nerdctl/image-digest label, and use it for the in-use lookup. The digest comes from the image nerdctl has already resolved, so nothing extra is fetched, and the label is read from the metadata the listing has already loaded (WithoutRefreshedMetadata), so the lookup costs no additional round trip.
Compatibility
Containers created before this label existed, or created outside nerdctl (ctr, kubelet, another client), have no such label. For those the previous behavior is kept as a fallback: they are still resolved by name. No state migration is needed and no existing container changes behavior for the worse.
An unparsable label value falls back the same way rather than dropping the container from the in-use set. Dropping it would be the more harmful failure: the image would look free, and anything built on this lookup would offer to reclaim space that is actually held.
Why it matters beyond the indicator
The same lookup backs the ACTIVE and RECLAIMABLE columns of
nerdctl system df(follow-up, #3942). There a misattributed container is not a single letter in a column: the unique layers of an image that is actually in use get counted as reclaimable space, which is exactly the number a user acts on when deciding what to delete.Tests
TestPinnedImageDigestcovers the four label states: pinned, absent, empty, unparsable.TestImages/In use survives a retagreproduces the scenario end to end and asserts both sides: the image the container runs keepsU, the image the tag now points at does not.The in-use lookup was introduced in #5093.