Docker Remove Image: How to Delete Docker Images Explained with Examples

As a full-stack developer, you know that working with Docker can greatly simplify deploying and scaling your applications. However, one side effect of using Docker heavily is that over time, you tend to accumulate a large number of Docker images. Each time you pull an image, build a new version of an image, or even just start and stop containers, the number of images stored on your machine grows.

While disk space may be relatively cheap these days, letting Docker images grow unchecked can lead to some problems:

  • Slower performance as your machine runs low on disk space
  • Difficulty pulling new images if your disk is full
  • Security vulnerabilities in old, unpatched images
  • Wasted space from images you no longer need

I‘ve certainly run into issues where a build server or development machine starts failing due to full disks, and the culprit turns out to be an excessive number of Docker images. One team I worked on had a Jenkins server with over 500GB of old build images!

Why Remove Images?

You might be thinking, "Why bother removing images? Storage is cheap and plentiful." While that‘s true to an extent, there are a few reasons you might need to clean up your Docker images:

  • Reclaiming disk space: In my experience, it‘s quite easy for a development machine or build server to accumulate many gigabytes of unneeded images over time. If you‘re running low on disk space, removing old images can be a quick way to free up significant space.

  • Troubleshooting issues: Sometimes, an issue with a container can be resolved by removing and re-pulling the underlying image to get a fresh version. I‘ve had cases where a container wouldn‘t start due to corruption in the stored image layers.

  • Updating/patching images: When a new version of a base image is released to address security issues or bugs, you‘ll want to remove the old images to ensure your containers are running the patched versions.

  • Regular cleanup: Even if you‘re not critically low on disk space, it‘s a good practice to periodically review and clean up your images. This can be part of a monthly or quarterly maintenance process to keep your Docker environment running smoothly.

Docker Image Growth Over Time

To illustrate how quickly Docker image disk usage can grow, here‘s some data from a real-world example. This is from a Jenkins build server I managed that ran daily builds for several projects:

Month Number of Images Total Size (GB) Percent Growth
January 1,254 510 GB
February 1,976 630 GB 24%
March 2,433 725 GB 15%
April 3,120 910 GB 26%

In the span of just 4 months, the number of images more than doubled and the disk usage nearly doubled. The growth wasn‘t linear, as it depended on factors like the number of builds run and whether we cleaned up any old images. But the trend is clear – Docker images will grow over time if not managed.

From my analysis of the images on this server, the average image size was around 300-400MB. Your image sizes may be smaller or larger, but it gives a rough idea. With over 3,000 images, it‘s easy to see how the gigabytes add up.

Listing and Inspecting Docker Images

Before we start deleting images, let‘s review how to list the images on your system using the docker images command:

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
myapp               latest              8d5db0d5ffa6        3 minutes ago       128MB
python              3.8-slim-buster     214d62795dbb        2 days ago          114MB
node                14-alpine           0da9cca9d57d        2 weeks ago         89.3MB
postgres            13                  d3123ac9f45a        2 weeks ago         314MB
mysql               8                   a8a59477268d        2 weeks ago         514MB

This shows the repository, tag, image ID, creation date, and size for each image. Several of these images, like python, node, and mysql are base images that were likely pulled from Docker Hub. The myapp image was probably built from a Dockerfile locally.

To get more details about a particular image, use the docker inspect command with either the repository:tag or image ID:

$ docker inspect myapp:latest
[
    {
        "Id": "sha256:8d5db0d5ffa6f2a2331a8e0f8e2fdb9a0a9a1a3f2a2f1a8e0f8e2fdb9a0a9a1a",
        "RepoTags": [
            "myapp:latest"
        ],
        "RepoDigests": [],
        "Parent": "sha256:c5701e02ed095ae7cabaef9fcef009d1f272206b13ffbb171a79326ac3f31eb2",
        ...

The inspect output shows more complete information about how the image was built, its configuration, and the parent layers. This can be helpful when trying to determine if an image is still needed or can be removed safely.

Removing Docker Images

The main command to delete images is docker image rm, which accepts one or more image names or IDs. If an image has multiple tags referencing it, you must remove all of them before the image is deleted.

Here‘s an example of removing an image by its ID:

$ docker image rm 8d5db0d5ffa6
Untagged: myapp:latest
Deleted: sha256:8d5db0d5ffa6f2a2331a8e0f8e2fdb9a0a9a1a3f2a2f1a8e0f8e2fdb9a0a9a1a

You can also remove images by repository and tag:

$ docker image rm myapp:latest
Untagged: myapp:latest
Deleted: sha256:8d5db0d5ffa6f2a2331a8e0f8e2fdb9a0a9a1a3f2a2f1a8e0f8e2fdb9a0a9a1a

To remove multiple images at once, simply list them all:

$ docker image rm myapp:latest python:3.8-slim-buster

You can also use wildcards to match image names:

$ docker image rm my*

This would remove any images starting with "my".

Sometimes you‘ll see images with <none> as the repository and tag. These are dangling images that have lost their tag references, either because you built a new version of an image or because you deleted the tag. To clean up just dangling images, use:

$ docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Deleted Images:
5a6ae2b7fb4f51a5e514b7a44906f978e378fc15e7143e33de214a760cbd9765
e9d88e2efb3f2fab3963ec9e3a1250f4ec03365307f602f27f5a15f41ecb2b8b

Total reclaimed space: 364.5MB

The docker image prune command will prompt for confirmation, then delete any dangling images, showing the reclaimed space.

Advanced Image Removal

In addition to specifying images by full ID or name, the docker image rm command also accepts filters to narrow down the list of images to remove. Some useful filters:

  • --filter "until=24h" – Remove images created more than 24 hours ago
  • --filter "label=deprecated=true" – Remove images with the label deprecated=true
  • --filter "dangling=false" – Remove non-dangling images

You can also force remove images with the -f or --force flag. This will remove the image even if it‘s in use by stopped containers or has multiple tags. For example:

$ docker image rm -f myapp:latest

Use docker image rm -f with caution, as it can disrupt existing containers and cause data loss if you accidentally remove an image that‘s still needed.

Removing Unused Images

In addition to dangling images, another category of images that tend to accumulate are ones that have been pulled or built but never used to start a container. The docker image prune command has an -a or --all flag to remove all unused images, not just dangling ones:

$ docker image prune -a
WARNING! This will remove all images without at least one container associated to them.
Are you sure you want to continue? [y/N] y
Deleted Images:
untagged: postgres:13
untagged: postgres@sha256:7130925642f187d44324915e7d83e4a0f73cbb4b3fb82bce8cabe1ef993bfd44
deleted: sha256:d3123ac9f45a2f5cfe77b8adf5ea2b63def4d64c622a9ffac7f5dd07e5a1312a
deleted: sha256:6c9eaf4bd2d1d1c33bbb0dbe9d0a13c220b4caaaa0938a12d42159b31ae696cf

Total reclaimed space: 205.1MB

Note this is much more aggressive than just removing dangling images, as it will delete any images not currently in use by a container. Be sure you really want to delete all unused images before running this!

Best Practices for Managing Docker Images

While it‘s good to periodically clean up unnecessary images, there are some steps you can take to minimize image cruft in the first place:

  • Use specific tags for images instead of relying on the generic latest tag. This makes it easier to identify and remove outdated images later. For example, tag your app images with the build number or git commit hash.

  • When building images, use multi-stage builds where possible to minimize the size of the final image. Smaller images mean faster download times and less disk usage. Multi-stage builds let you use a large image with all your build tools for the build steps, but copy only the necessary artifacts into a small final image.

  • Use dockerignore files to exclude unnecessary files and folders when building images. This also helps keep image sizes down. Be sure to exclude things like build artifacts, log files, and caches that aren‘t needed in the final image.

  • Store images you want to keep long-term in a private registry instead of just on your local machine. You can set up an automated process to periodically clean old images from the registry based on age or tags. This keeps your image library available but not taking up unnecessary disk space on individual machines.

  • If you have a CI/CD pipeline to build, test, and deploy your apps, have it automatically clean up images from previous builds on the build server or runners. There‘s usually no need to keep old intermediate build images around after the build completes. Configure your build jobs to always remove old images when done.

Real-World Example

To illustrate the benefits of removing unused Docker images, here‘s an anecdote from my experience:

We had a small development team that was using Docker heavily for their local development environments and build pipelines. Over the course of a few months, they noticed their Jenkins server jobs were taking longer and longer to run. Sometimes jobs would even fail with "no space left on device" errors.

When I investigated, I found that the Jenkins server had accumulated over 600GB of old Docker images from the daily automated builds! Most were outdated app versions, intermediate build layers, or base images no longer in use.

I used the docker image prune -a command to remove all images not currently in use by running containers. The result was over 400GB of disk space reclaimed. Builds sped up significantly now that they weren‘t constrained by low disk space. As a longer term fix, we updated the Jenkins pipeline to always remove its build images when done and set up a registry server for storing images we actually needed to keep around.

The team was able to reclaim a significant amount of wasted disk space and improve the reliability of their build pipeline, thanks to removing old Docker images!

Conclusion

Knowing how to remove Docker images is an essential skill for managing disk space and keeping your Docker environment running smoothly. The docker image rm and docker image prune commands give you flexibility to delete images by ID, name, or using filters. For more advanced cleanup, you can use commands like docker system prune to remove all unused images, containers, and networks at once.

Incorporating Docker image best practices into your workflow, like using specific tags, multi-stage builds, and registries for long-term storage can help slow the accumulation of unneeded images.

By periodically reviewing and cleaning up your Docker images, and setting up automated cleanup processes in your build pipelines, you can keep your Docker environment lean and performant. The disk space and time savings can really add up, especially when you‘re working with large applications or CI/CD pipelines.

Additional Resources

If you‘d like to learn more about working with Docker images and other cleanup techniques, check out these resources:

I hope this in-depth look at removing Docker images has been helpful! With the right commands and some regular cleanup, you can keep your Docker environment running smoothly. Feel free to reach out if you have any other Docker questions or tips to share.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *