Docker: Tidying up containers and images during dev

April 28, 2019 0 By Toby Worth

Firstly, it needs to be said, you probably *shouldn’t* have a lot of containers lying around, since it’s not the ‘docker way’ to create containers as if they were permanent entities that need to preserving. That’s kind of the opposite of the idea of Docker, in fact. The things that need to be preserved are the docker files, docker compose files and, arguably, the images you generate from them.

Think of containers as just running instances of your images – that are run, stopped and removed as if they were streakers at a football game. Wait.. what? Erm, whatever, they’re basically totally disposable and you just get another one when you least expect need it.

So, when you’re developing your containers, use the ‘–rm’ flag to get the container removed for you when it stops. e.g. ‘docker run –rm <image>’

However, shit happens. If you’re getting a lot of orphaned containers or images lying around in your ‘docker ps -a’ and ‘docker images’ listing, then you can run a couple of simple commands to tidy things up.

Removing Containers

OK, make sure you’re running BASH terminal, these commands won’t work in others. Firstly, lets have a look at the list:

Type ‘ docker ps -a’ to see a full list of containers (the ‘-a’ flag includes the non-running containers). run it again with the ‘-q’ flag to show only the IDs of the containers: ‘docker ps -a -q’

The command for removing containers is ‘docker rm [containerid]’. So, to remove ALL containers, type:

docker rm $(docker ps -a -q)

This passes the list of all container IDs to the ‘docker rm’ command. If you’ve let things get messy, this could take a minute, but it shows you progress as it goes.

To remove all images that match a query

Similarly to the container removal, you’re basically passing image IDs to a docker command, but the image-removal command is ‘docker rmi’ (not the addditional ‘i’).

Now, it’s highly unlikely that you’ll need to remove ALL images, so we need to call the removal function while providing a filter, which in my case is all those images that got created without tags.

So the inner, filtering command is:

docker images | grep "^<none>" | awk '{print $3}'.

Let’s break that down.

‘docker images’ lists all the images on the host. The output of this is passed to grep, via the pipe symbol (‘|’) which filters the list of images to just those that have ‘<none>’ in their metadata (‘<none>’ was the value of the tag column, in my case).

The last part, AWK, is an incredibly useful *nix tool that lets you manipulate data streams in the CLI. It can take many inputs (files, streams, stdout etc.), but we’re using the output of the previous grep command as input. What the ‘{print $3}’ argument does is to only return the 3rd column of data from the input values. If you look at the results of ‘docker images’ in another terminal, you can see that that is the one that contains the image IDs.

Now, we can put that together with the docker rmi command like this:

docker rmi $(docker images | grep "^<none>" | awk '{print $3}')  

You should see a list of deletions appear, with the images and associated layers (e.g. the ones from the various stages in the dockerfiles that built those images).

That should free up some space.