drmi - a tool for cleaning up Docker images

drmi - a tool for cleaning up Docker images

This tool is available as part of my dockertools project on GitHub

As I am doing work on containers, I have occasionally run into cases where I need to do tasks that involve a lot of repitition. I had recently been playing around with running minikube directly in containers. It works great, but it also creates a lot of images around:


$ docker images | cut -d " " -f 1 | grep k8s
k8s.gcr.io/kube-proxy-amd64
k8s.gcr.io/kube-apiserver-amd64
k8s.gcr.io/kube-scheduler-amd64
k8s.gcr.io/kube-controller-manager-amd64
k8s.gcr.io/etcd-amd64
k8s.gcr.io/kube-addon-manager
k8s.gcr.io/k8s-dns-dnsmasq-nanny-amd64
k8s.gcr.io/k8s-dns-sidecar-amd64
k8s.gcr.io/k8s-dns-kube-dns-amd64
k8s.gcr.io/pause-amd64
k8s.gcr.io/kubernetes-dashboard-amd64
gcr.io/k8s-minikube/storage-provisioner

So I wanted to create a way to remove all these images without typing out the names - the default docker rmi command is pretty limited and requires you to enter each image name and tag individually. I had recently created a script called ctsh that allows you to easily run a command in a container by only specifying part of the image name that the container is running, part of the container name, or part of the container id:


$ ctsh nginx hostname
/usr/bin/docker exec -it ece05a2706da hostname
ece05a2706da

Using parts of this script, I created drmi so that you can easily remove a bunch of images by only specifying part of the image name or the image id. For example, say I have these images (ignoring my k8s images):


$ docker images | tr -s ' ' | cut -d ' ' -f 1-2 | grep -v REPOSITORY | grep -v k8s
nginx latest
debian stretch
openshift/origin-pod v3.9.0
ubuntu latest

Removing these is complicated because in a couple cases I not only have to specify the image, I have to specify the version (for example, debian and stretch) even though there is only one version of each of the images. Doing this with drmi is pretty easy:


$ drmi ngi
Remove image nginx                                      latest              3c5a05123222        4 days ago          109MB (y/N)? y
/usr/bin/docker rmi 3c5a05123222
Untagged: nginx:latest
...
$ drmi deb
Remove image debian                                     stretch             9a5d7185d3a6        2 weeks ago         101MB (y/N)? y
/usr/bin/docker rmi 9a5d7185d3a6
Untagged: debian:stretch
...
$ drmi open
Remove image openshift/origin-pod                       v3.9.0              57d7271f57d2        4 weeks ago         223MB (y/N)? y
/usr/bin/docker rmi 57d7271f57d2
Untagged: openshift/origin-pod:v3.9.0
...
$ drmi ubu
Remove image ubuntu                                     latest              113a43faa138        5 weeks ago         81.2MB (y/N)? y
/usr/bin/docker rmi 113a43faa138
Untagged: ubuntu:latest
...

Note that it can only remove images if they aren't in running containers - I will eventually enhance this so that it can stop containers that are running the image you are trying to remove, but for now you'll get an error and you'll have to stop the container first. For example, if I have a running nginx container, I won't be able to remove nginx:


$ drmi ngi
Remove image nginx                                      latest              3c5a05123222        4 days ago          109MB (y/N)? y
/usr/bin/docker rmi 3c5a05123222
Error response from daemon: conflict: unable to delete 3c5a05123222 (cannot be forced) - image is being used by running container c97deda5a43e

For now, I don't automatically remove an image if there is a stopped container unless you pass in a -f flag:


$ drmi ngi
Remove image nginx                                      latest              3c5a05123222        4 days ago          109MB (y/N)? y
/usr/bin/docker rmi 3c5a05123222
Error response from daemon: conflict: unable to delete 3c5a05123222 (must be forced) - image is being used by stopped container c97deda5a43e

$ drmi -f ngi
Remove image nginx                                      latest              3c5a05123222        4 days ago          109MB (y/N)? y
/usr/bin/docker rmi -f 3c5a05123222
Untagged: nginx:latest
...

Now I can easily remove all my k8s images like this:


$ yes | drmi -f k8s
Remove image k8s.gcr.io/kube-scheduler-amd64            v1.10.0             704ba848e69a        3 months ago        50.4MB (y/N)? 
/usr/bin/docker rmi -f 704ba848e69a
Untagged: k8s.gcr.io/kube-scheduler-amd64:v1.10.0
Untagged: k8s.gcr.io/kube-scheduler-amd64@sha256:4670717a1c092680dc0ac018dc36f991e06ffbee6b6bafba9a2968d7bebe7800
Deleted: sha256:704ba848e69a76e2a8886c64d70971c9db1398ee4d02cbccf61572b1237b545a
Remove image k8s.gcr.io/kube-controller-manager-amd64   v1.10.0             ad86dbed1555        3 months ago        148MB (y/N)? 
/usr/bin/docker rmi -f ad86dbed1555

I also noticed that I sometimes have images lingering around that don't have a name/tag:


$ docker images | tr -s ' ' | cut -d ' ' -f 1-3
REPOSITORY TAG IMAGE
<none> <none> 44f78fe63fd9
<none> <none> bfda2fbbe4e3
<none> <none> a7dcc43d3a6c
<none> <none> f709d18f4646
<none> <none> d2d91117e723

To make it easy to clean these up, I added a -u flag. It can be used in combination with the -f flag if there are stopped containers using these images. So cleaning up these is just:


$ yes | drmi -u
Remove image <none>              <none>              44f78fe63fd9        2 minutes ago       81.2MB (y/N)? 
/usr/bin/docker rmi 44f78fe63fd9
Deleted: sha256:44f78fe63fd9d8996d740a0250dc727a9b20ab5521689f823be3e710de164943
Remove image <none>              <none>              bfda2fbbe4e3        2 minutes ago       81.2MB (y/N)? 
/usr/bin/docker rmi bfda2fbbe4e3
...

TODO

  • add flag for stopping running containers using matching images to be removed
  • better command line switch processing
  • better output formatting
  • add similar command to stop containers based on a partial name

Related Article