docker / cli

The Docker CLI
Apache License 2.0
4.91k stars 1.93k forks source link

Keep tag of indirect used images while docker image prune -a #3579

Open PMExtra opened 2 years ago

PMExtra commented 2 years ago

Steps to reproduce the issue:

  1. Build a local image that FROM image_foo
  2. Run a container with the local image
  3. Execute docker image prune -a

Describe the results you received:

The image_foo will be untagged.

Describe the results you expected:

The image_foo cannot be truly removed, because it's an indirect depend of the running container.

So I think we can keep the tag.

Generally, we use prune because we want to free up storage. But removing a tag doesn't work for the goal. It just made more dangling images and more confusing.

Additional information you deem important (e.g. issue happens only occasionally):

Output of docker version:

Client: Docker Engine - Community
 Version:           20.10.11
 API version:       1.41
 Go version:        go1.16.9
 Git commit:        dea9396
 Built:             Thu Nov 18 00:36:58 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.11
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.9
  Git commit:       847da18
  Built:            Thu Nov 18 00:35:20 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.12
  GitCommit:        7b11cfaabd73bb80907dd23182b9347b4245eb5d
 runc:
  Version:          1.0.2
  GitCommit:        v1.0.2-0-g52b36a2
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
thaJeztah commented 2 years ago

Thanks for your proposal.

The image_foo cannot be truly removed, because it's an indirect depend of the running container.

The relation in this case would only be when using the "classic" builder, and only for the build-cache. The image that's produced does not have a relation with the original image (other than sharing the same layers). When using BuildKit as builder (DOCKER_BUILDKIT=1) the build-cache is fully separate from the image-cache, so there won't be a direct relation between the two (even for build).

That said, you can label the original image, and use that to exclude it from being pruned, and there are some proposals, such as https://github.com/docker/cli/issues/3557 and https://github.com/docker/cli/issues/3027 (some other ones as well) to provide more options on "filtering" what will be pruned.

jasonheffnerpsu commented 4 months ago

It took me some searching to come across this open issue.

I've run into the same issue with docker system prune -a but in more complex deployments between images that are built using the same CI build cache. I've also run into this with common images, nginx, traefik, I use on deployments where the previous tags just disappear which causes issues. I stopped using "-a" for this reason on deployments for cleaning up storage. My future plan is to add a BUILD_ID as a last step to introduce unique images across branches, but this doesn't fix pulled images from other sources.

I thought this test case might illustrate it better

> docker pull alpine:latest

> docker tag alpine:latest alpine:test

> docker images

REPOSITORY TAG IMAGE ID CREATED SIZE alpine latest 442043f030d3 13 days ago 8.83MB alpine test 442043f030d3 13 days ago 8.83MB

> docker run -d --name container1 alpine:latest sleep 1000

> docker run -d --name container2 alpine:test sleep 1000

> docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 30bf5bd9e47b alpine:test "sleep 1000" 5 seconds ago Up 4 seconds container2 968ab6b0c24d alpine:latest "sleep 1000" 11 seconds ago Up 10 seconds container1

> docker system prune -a -f

Deleted Images: untagged: alpine:latest

Total reclaimed space: 0B

> docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 30bf5bd9e47b alpine:test "sleep 1000" 3 minutes ago Up 3 minutes container2 968ab6b0c24d 442043f030d3 "sleep 1000" 3 minutes ago Up 3 minutes container1

As you can see the image for the running container has been untagged. In this test case it happens to also be removed.