If there are multiple image tags for a used image, docker image prune -a
will keep the alphabetically last tag. Please see a reproducible example at the bottom.
Is there a way to influence which tags will be kept? Ideally, I would like docker image prune -a
to keep all image-tag combinations that are in use (in use includes stopped containers).
Reproducible example (careful as it will delete images from your docker system):
# docker image prune -a keeps hellow-world:x
docker pull hello-world
docker tag hello-world:latest hello-world:x
docker tag hello-world:latest hello-world:a
docker run hello-world:x
docker run hello-world:a
docker image prune -a
# Reset
docker system prune -a
# docker image prune -a keeps hellow-world:z
docker pull hello-world
docker tag hello-world:latest hello-world:x
docker tag hello-world:latest hello-world:z
docker run hello-world:x
docker run hello-world:z
docker image prune -a
I don't know of a way to do it natively with the docker
cli, but a combination of awk
/sed
can help.
myhost:~# docker pull hello-world
myhost:~# docker tag hello-world:latest hello-world:x
myhost:~# docker tag hello-world:latest hello-world:z
myhost:~# docker run hello-world:x
myhost:~# docker run hello-world:z
Instead of using prune
, we'll generate the list of images and then send to docker rmi
instead:
myhost:~# docker ps -a --format '{{.Image}}' > ps_images
myhost:~# cat ps_images
hello-world:z
hello-world:x
myhost:~# docker images --format '{{.Repository}}:{{.Tag}}' | sort -r
hello-world:z
hello-world:x
hello-world:latest
Those are the images as they might be pruned, where (due to the sort -r
) hello-world:z
should be retained since it is the lexicographically last image for hello-world
. If we filter out images found in the preceding docker ps -a
command, we should preserve both :z
and :x
, which in this case means removing :latest
.
myhost:~# docker images --format '{{.Repository}}:{{.Tag}}' | sort -r \
| awk -F: '{arr[$1]++;print(arr[$1],$1 ":" $2);}' \
| sed -nE 's/^([^1] |1[^ ]+ )(.*)/\2/gp' | grep -f ps_images -v
hello-world:latest
We can send this directly to docker rmi
:
myhost:~# docker images --format '{{.Repository}}:{{.Tag}}' | sort -r \
| awk -F: '{arr[$1]++;print(arr[$1],$1 ":" $2);}' \
| sed -nE 's/^([^1] |1[^ ]+ )(.*)/\2/gp' | grep -f ps_images -v \
| xargs docker rmi
Untagged: hello-world:latest
myhost:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world x feb5d9fea6a5 15 months ago 13.3kB
hello-world z feb5d9fea6a5 15 months ago 13.3kB
Walk-through:
sort -r
orders them with latest-first
awk ...
numbers them by the first component of the image name, where its output is
1 hello-world:z
2 hello-world:x
3 hello-world:latest
sed ...
removes the 1
lines
grep ...
removes images that we discovered from docker ps -a
in the first code block (the -v
is inverting the match)
xargs ...
sends the output lines (hello-world:latest
in this case) as individual arguments to docker rmi