Skip to content

c8d/prune: Fix images being deleted when they're still used with a different reference#45839

Merged
thaJeztah merged 5 commits intomoby:masterfrom
vvoland:c8d-dont-prune-used
Jun 30, 2023
Merged

c8d/prune: Fix images being deleted when they're still used with a different reference#45839
thaJeztah merged 5 commits intomoby:masterfrom
vvoland:c8d-dont-prune-used

Conversation

@vvoland
Copy link
Copy Markdown
Contributor

@vvoland vvoland commented Jun 28, 2023

- What I did
Fixed image prune -a deleting dangling images used by containers.

- How I did it

  • Exclude dangling tag of the images used by containers (this makes sure that if the original image was deleted we don't delete the dangling image)
  • Exclude images that are used by containers which were started by specifying an image ID instead of a specific name.

- How to verify it

$ make TEST_INTEGRATION_USE_SNAPSHOTTER=1 \
       DOCKER_GRAPHDRIVER=overlayfs \
       TEST_FILTER=TestPruneDontDeleteUsedDangling \
       test-integration
...
INFO: Testing against a local daemon
=== RUN   TestPruneDontDeleteUsedDangling
--- PASS: TestPruneDontDeleteUsedDangling (0.07s)
PASS

DONE 1 tests in 1.079s

- Description for the changelog

containerd integration: `docker image prune -a` no longer removes images still in use by running containers

- A picture of a cute animal (not mandatory but encouraged)

@vvoland vvoland added status/2-code-review area/images Image Distribution kind/bugfix PR's that fix bugs containerd-integration Issues and PRs related to containerd integration process/cherry-pick/24.0 labels Jun 28, 2023
@vvoland vvoland added this to the 25.0.0 milestone Jun 28, 2023
Copy link
Copy Markdown
Member

@laurazard laurazard left a comment

Choose a reason for hiding this comment

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

LGTM

@thaJeztah
Copy link
Copy Markdown
Member

Looks like there's a failure;

=== FAIL: github.com/docker/docker/integration/image TestPruneDontDeleteUsedDangling (0.03s)
    prune_test.go:23: assertion failed: error is not nil: Error response from daemon: No such image: sha256:0df1207206e5288f4a989a2f13d1f5b3c4e70467702c1d5d21dfc9f002b7bd43

@thaJeztah
Copy link
Copy Markdown
Member

I'm wondering though; if 2 images are tags for the same digest, wouldn't we have to use the reverse? Untag the image, and let containerd prune / garbage collect unused content?

(If we use "force", them probably we must change the tag name to a dangling image name instead)

@thaJeztah
Copy link
Copy Markdown
Member

(I'm not sure if that would still provide us a way to report the amount of space we reclaimed though)

@thaJeztah
Copy link
Copy Markdown
Member

Discussing with @neersighted and we were considering if we should take a different approach in general;

  • whenever we create an image, always create two images:
    • 1 image with the name:tag (if any)
    • 1 "dangling" image
  • the second one is effectively replacing the graph driver "content addressable" store (access image by digest)

Now when we remove an image; we either remove the image's name:tag from containerd's store, or the dangling image name (if there's no more references to it).

So instead of creating dangling image references "on the fly", we can create them up-front, and use them for reference counting on our side

@vvoland vvoland force-pushed the c8d-dont-prune-used branch from 577f7c1 to 1d6d432 Compare June 29, 2023 14:03
@vvoland
Copy link
Copy Markdown
Contributor Author

vvoland commented Jun 29, 2023

Ah, the failure is on Windows only, because the hack/make/.build-empty-images doesn't run on Windows, so there's no special dangling image.

So instead of creating dangling image references "on the fly", we can create them up-front, and use them for reference counting on our side.

I thought about it before, but it seemed to be a bit more tricky because the image creation is not always on our side (for example building image with Buildkit) whereas it's more common for Moby to perform image deletion.

On the other hand, that would indeed give us more control over the GC and would make more sense in cases where an explicit image digest is used instead of a name (so for example docker run 3abd238 wouldn't pick any image that points to the sha256:3abd238...).

We could give it a try and see if that doesn't complicate things too much. It's a bit orthogonal to this PR though, so possibly we should just fix this issue here and then continue in a follow-up/separate ticket.

I'm wondering though; if 2 images are tags for the same digest, wouldn't we have to use the reverse? Untag the image, and let containerd prune / garbage collect unused content?

Yes, this will cause the unused tag which also points to the same target as the used tag.
Looks like this can be fixed easily by just always excluding the dangling image of the container image.

Also, there's another unsolved issue - images referenced by their id (docker run 2376a0c12759aa or docker run sha256:...) will be pruned.

Fixed it now.

Copy link
Copy Markdown
Member

@neersighted neersighted left a comment

Choose a reason for hiding this comment

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

Some initial nits, though I'm not a fan of how imperative this code is, and I think I might send a PR to your branch with a restructured implementation that keeps each category of prune exclusion more discrete.

@vvoland vvoland force-pushed the c8d-dont-prune-used branch from 1d6d432 to c9d8569 Compare June 30, 2023 09:18
@vvoland vvoland changed the title c8d/prune: Exclude used images by id c8d/prune: Fix images being deleted when they're still used with a different reference Jun 30, 2023
Copy link
Copy Markdown
Member

@neersighted neersighted left a comment

Choose a reason for hiding this comment

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

One nit, but overall LGTM. I think that we should restructure this logic in the future, but I think that we can take this as an improvement for now, and think about lifecycle management more holistically in the future (during which we can revisit this logic, and perhaps even generalize it).

@vvoland vvoland force-pushed the c8d-dont-prune-used branch from c9d8569 to edbfecb Compare June 30, 2023 16:09
Copy link
Copy Markdown
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

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

LGTM (but let me know if you want to address that nit; not a blocker)

vvoland added 5 commits June 30, 2023 18:18
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
So we don't override the original Labels in the passed image object.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
If an image is only by id instead of its name, don't prune it
completely. but only untag it and create a dangling image for it.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
@vvoland vvoland force-pushed the c8d-dont-prune-used branch from edbfecb to e638351 Compare June 30, 2023 16:19
Copy link
Copy Markdown
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

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

LGTM

@neersighted
Copy link
Copy Markdown
Member

Backported at #45857

@thaJeztah
Copy link
Copy Markdown
Member

@neersighted commits still align? I see there may be a potential race condition between you cherry-picking and Pawel force-pushing 😓 🙈

@neersighted
Copy link
Copy Markdown
Member

That's one of the things to check when reviewing a backport PR 😉

But yes, I made sure to re-cherry (with rerere) once Pawel pushed again; all SHAs are aligned to the latest version of this PR.

@thaJeztah
Copy link
Copy Markdown
Member

Thanks!

@thaJeztah
Copy link
Copy Markdown
Member

Timeout in one of the BuildKit tests (panic: test timed out after 30m0s); kicked it again

@thaJeztah thaJeztah merged commit a61494e into moby:master Jun 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/images Image Distribution containerd-integration Issues and PRs related to containerd integration kind/bugfix PR's that fix bugs process/cherry-picked status/4-merge

Projects

Development

Successfully merging this pull request may close these issues.

[containerd snapshotter] Prune attempts to remove untagged/dangling images still in use by running containers

4 participants