Remove Docker Images with PowerShell

Update: Since Docker 1.13 (API version 1.25) the prune command has been available. You can remove all unused images with > docker image prune –all

If like me, you’ve been experimenting with Docker since Microsoft made the Dynamics NAV images available, you’ll probably notice you’re using up a fair bit of hard drive space. So how do we remove Docker Images?

Dynamics NAV Docker Images
Dynamics NAV Docker Images

The image above is a tad misleading however, as Docker shares images saving space. The microsoft/windowsservercore image for example is around 10GB, and is reused by all the other Dynamics NAV images. The size you see in the screenshot above is the total size of the image if you were to save an archive using the docker save command. Still, my Docker folder was somewhere around 40-50GB in size.

So today I decided to have a clean up and remove all the images from my machine. I could have removed each image one by one using docker rmi:

> docker rmi ee0
> docker rmi bfe
> docker rmi 7fc

Docker tip: When referencing Docker Image or Containers in Docker commands, for brevity, you can use the first x number of characters of the Image or Container ID. Where x is the minimum number needed to identify a unique ID on your system. The first three characters will be fine in most cases.

But.. repetition is a computers job right?

To automate this we’ll need to get a list of our Docker Image IDs and pass them to the docker rmi command.

To get a list of Image IDs on our system, we can use the docker images command with the -q option:

Get Docker Image IDs
Get Docker Image IDs

We can then take the list of image IDs and iterate through them using a PowerShell foreach statement:

$images = docker images -q

foreach ($image in $images) {
 docker rmi $image -f
}

What about filtering?

So far so good.. we can remove Docker images with a PowerShell script. But what if we want to keep the base image? It’s around 12GB, so we probably don’t want to download it again next time we pull a NAV image.

The docker images command takes the repository name as an optional parameter. We can use this to filter on our NAV images:

> docker images microsoft/dynamcis-nav
List NAV Docker Images
List NAV Docker Images

Keeping the base image

The problem is, unless we’ve explicitly requested the base image it doesn’t show up in our image list. This means it will get removed with the last NAV image referencing it. To get around this we just need to do a pull request for the base image.

To understand this concept, it’s important to know that Docker images are built in layers. Instead of building an entire image from scratch every time, when creating an image you can base it on an existing image. All Dynamics NAV images are built on an image called microsoft/nav-docker. Docker images can be built from a Dockerfile. We can view the Dockerfile for microsoft/nav-docker and see that this image is currently based on the microsoft/dotnet-framework:4.7-windowsservercore image.

So back to the pull request:

> docker pull microsoft/nav-docker
Cant Pull nav-docker image
Cant Pull nav-docker Image

Microsoft has restricted access, or just not published this image. We can use the image that microsoft/nav-docker is based on instead:

> docker pull microsoft/dotnet-framework:4.7-windowsservercore
Pull microsoft/dotnet-framework:4.7-windowsservercore
Pull microsoft/dotnet-framework:4.7-windowsservercore

Running this command didn’t download the image again as Docker found it locally. However, it will now list the microsoft/dotnet-framework:4.7-windowsservercore image alongside our NAV images:

Docker Images with a base image available
Docker Images with a base image available

As we can see from the size attributes, the 4.7-windowsservercore image makes up the bulk of the NAV image size.

To remove all the microsoft/dynamics-nav images but leave the microsoft/dotnet-framework image for later use, we can run the following PowerShell script:

$images = docker images -q microsoft/dynamics-nav

foreach ($image in $images) {
 docker rmi $image -f
}

Remove Docker Images.. except the most recent

To have a look at another filtering option lets explore another scenario. What if we want to keep the most recently pulled NAV image, but remove Docker images previous to this?

The docker images command has a –filter option. We can use this to filter on the image created date. It’s important to note that this is based on the time the images were created on your system (when it was pulled), not when the vendor created or published the image.

Using a before filter we can get a list of all image IDs that where pulled before microsoft/dynamics-nav:latest:

> docker images microsoft/dynamics-nav --filter "before=microsoft/dynamics-nav:latest"
$images = docker images -q microsoft/dynamics-nav --filter "before=microsoft/dynamics-nav:latest"

foreach ($image in $images) {
 docker rmi $image -f
}

Putting the two commands together

So far we’ve used a foreach loop to iterate through the list of image IDs we get back from the docker images command. I think this approach makes the script easier to read, but we can also use this list directly with the docker rmi command on the same line:

> docker rmi (docker images -q microsoft/dynamics-nav --filter "since=microsoft/dynamics-nav:latest")

In the example above I’ve used the since filter to remove all NAV images after the “latest” image.

Now I’m left with just the latest Dynamics NAV image and the dotnet-framework image it’s based on.

Dynamics NAV latest Docker image
Dynamics NAV latest

OK, well thanks for reading. If you want to look at more of the filtering options available check out this link: https://docs.docker.com/engine/reference/commandline/images/#filtering”

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.