Prune unused images correctly

dangling=true doesn't prune any images, as we are not creating dangling
images.

Using --all should remove unused images, but it considers the Git SHA
tag on the latest image to be unused (presumably because there are two
tags, the SHA and latest and the running container is only considered to
be using "latest"). As a result it deletes the tag, which means that we
can't rollback to that SHA later.

Its a bit more complicated to only remove images that are not referenced
by any containers.

First we find the tags we want to keep from the containers (running and
stopped).

Then we append the latest tag to that list.

Then we get a full list of image tags and remove those tags from that
list (using `grep -v -w`).

Finally we pass the tags to `docker rmi`. That either deletes the tag if
there are other references to the image or both the tag and the image if
it is the only one.
This commit is contained in:
Donal McBreen
2023-05-25 16:32:54 +01:00
parent 602aa43496
commit ff7a1e6726
3 changed files with 15 additions and 4 deletions

View File

@@ -3,12 +3,15 @@ require "active_support/core_ext/numeric/time"
class Mrsk::Commands::Prune < Mrsk::Commands::Base
def images
docker :image, :prune, "--force", "--filter", "label=service=#{config.service}", "--filter", "dangling=true"
pipe \
docker(:image, :ls, *service_filter, "--format", "'{{.Repository}}:{{.Tag}}'"),
"grep -v -w \"#{active_image_list}\"",
"while read tag; do docker rmi $tag; done"
end
def containers(keep_last: 5)
pipe \
docker(:ps, "-q", "-a", "--filter", "label=service=#{config.service}", *stopped_containers_filters),
docker(:ps, "-q", "-a", *service_filter, *stopped_containers_filters),
"tail -n +#{keep_last + 1}",
"while read container_id; do docker rm $container_id; done"
end
@@ -17,4 +20,12 @@ class Mrsk::Commands::Prune < Mrsk::Commands::Base
def stopped_containers_filters
[ "created", "exited", "dead" ].flat_map { |status| ["--filter", "status=#{status}"] }
end
def active_image_list
"$(docker container ls -a --format '{{.Image}}\\|' --filter label=service=#{config.service} | tr -d '\\n')#{config.latest_image}"
end
def service_filter
[ "--filter", "label=service=#{config.service}" ]
end
end