Remove all untagged images from Docker using PowerShell

With multi-stage builds, you use multiple FROM statements in your Dockerfile. Each FROM instruction can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don’t want in the final image. However, every step creates a new, untagged image (or “dangling” image), which serves as the base for the next step. Having these untagged images in the Docker cache speeds up the build process, but consumes quite some disk space and clutters up the output of docker images.

I’ll provide two examples on how to delete these images on Linux and Windows.

Linux

On Linux this can be accomplished rather elegantly:

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

Windows

Windows PowerShell does not support grep and awk, so the result is more verbose:

docker rmi -f (docker images | findstr "^<none>" | %{ [regex]::split($_, "[\\s]+")[2]; })

Explanation

We gather a list of all untagged docker images, select the third column containing the image IDs and feed the result to docker rmi. Let’s have a look at the different components of this command line.

Force remove an image using the -f parameter:

docker rmi -f [IMAGE ID]

Pipe the list of all docker images to findstr, which works similar to grep, and filter on lines beginning with <none>:

docker images | findstr "^<none>"

Use a regular expression to split lines on [\\s]+, i.e. sequences of whitespace, then print the third column:

%{ [regex]::split($_, "[\\s]+")[2]; }"