How to Effectively Remove Docker Images and Containers
Docker has revolutionized how we build, package, and deploy applications by providing a lightweight and portable container runtime. Throughout the development process, you‘ll likely end up with a large number of Docker images and containers on your system. These can quickly consume significant disk space and resources, so it‘s important to clean them up periodically. In this article, we‘ll dive deep into everything you need to know to effectively remove Docker images and containers.
Understanding Docker Images and Containers
Before we get into the how, let‘s make sure we understand the what and why. Docker images are the blueprints from which containers are launched. They are made up of read-only layers that define the application and its dependencies. When you start a container, Docker creates a thin writable layer on top of the image layers.
Containers are the runnable instances of images. You can have many containers based off the same image. Containers encapsulate the application process and its isolated view of the operating system.
Over time, as you iterate on your application and rebuild images, you‘ll accumulate old image versions. Similarly, as you start and stop containers, the container instances will remain on disk even when not running. This is why cleaning up unused images and containers is necessary to reclaim disk space and keep your Docker environment tidy.
Removing Individual Docker Images
To delete a specific Docker image, you‘ll use the docker rmi
command followed by the image ID or tag. First, list the images on your system:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
myapp latest abc123def456 14 minutes ago 428MB
node 12 0b5da1e4b876 6 days ago 918MB
nginx alpine 377c0837328f 2 weeks ago 19.7MB
Then, remove an image by referencing its ID:
$ docker rmi abc123def456
Untagged: myapp:latest
Deleted: sha256:abc123def456...
You can also remove multiple images at once:
$ docker rmi abc123def456 0b5da1e4b876
If an image is tagged in multiple repositories, you must use the repository:tag notation or the image ID to remove it. Using just the tag will only untag the image, not delete it.
When deleting images, Docker will throw an error if the image is being used by any containers, including stopped ones. You‘ll need to remove the dependent containers first.
Removing Docker Containers
To delete a Docker container, use the docker rm
command with the container ID or name. First, list your containers:
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d7e1d3a87567 myapp:latest "docker-entrypoint.sā¦" 18 minutes ago Exited (0) 17 minutes ago mycontainer
Then, remove the container:
$ docker rm d7e1d3a87567
d7e1d3a87567
You can only remove stopped containers. If the container is still running, you‘ll get an error. Force remove a running container with the -f
flag:
$ docker rm -f d7e1d3a87567
Just like with images, you can delete multiple containers at once by providing their IDs/names.
Batch Removing All Unused Images and Containers
As you can imagine, removing images and containers one by one can be tedious. Docker provides the docker system prune
command to clean up unused images, containers, volumes, and networks with a single command:
$ docker system prune
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all dangling images
- all build cache
Are you sure you want to continue? [y/N] y
Deleted Containers:
d7e1d3a87567db...
f08dbbe0db0e7e...
Deleted Images:
untagged: myapp@sha256:abc123...
deleted: sha256:abc123def456...
untagged: node@sha256:def456...
deleted: sha256:def456abc123...
Total reclaimed space: 1.5GB
By default, this will remove:
- All stopped containers
- All networks not used by at least one container
- All dangling images (layers with no relationship to tagged images)
- All build cache
For a more aggressive clean, pass the -a
flag to remove all unused images, not just dangling ones.
You can also prune just images or just containers rather than the whole system:
$ docker container prune
$ docker image prune
Removing Images in a CI/CD Pipeline
Cleaning up old images is especially important in automated build pipelines, where a VM worker may process many builds over time. Leaving old images will slowly eat away at disk space until there is none left.
Here is an example of how to add a clean up step to a Jenkins declarative pipeline:
pipeline {
agent any
stages {
stage(‘Build‘) {
steps {
sh ‘docker build -t myapp:$BUILD_NUMBER .‘
}
}
stage(‘Push‘) {
steps {
sh ‘docker push myrepo/myapp:$BUILD_NUMBER‘
}
}
stage(‘CleanUp‘) {
steps {
sh ‘docker system prune -f‘
}
}
}
}
The -f
flag automatically confirms the deletion without prompting.
Avoiding the `–rm` Argument on `docker run`
You may have seen the advice to use --rm
when running containers to avoid having to manually delete them later:
$ docker run --rm -d --name mycontainer myimage
However, this practice is not recommended for a few reasons:
-
You lose the ability to inspect the container‘s logs or filesystem after it exits. This can make debugging issues more difficult.
-
Orchestrators and CI tools typically expect containers to remain after they exit for logging and auditing. Deleting them immediately can break integrations.
-
It doesn‘t actually solve image/layer cleanup, which is a larger concern for disk usage.
Instead, leave off --rm
and periodically run docker container prune -f
to retroactively clean up stopped containers.
Removing Images That Have Multiple Tags
Sometimes an image layer will be shared by multiple tagged images in different repositories. For example:
REPOSITORY TAG IMAGE ID CREATED SIZE
myapp v1 abc123def456 14 minutes ago 428MB
myapp latest abc123def456 14 minutes ago 428MB
company/myapp v1 abc123def456 14 minutes ago 428MB
All three tagged images share the same underlying layer abc123def456
. Removing any of the individual tags will untag that image but not remove the actual layer:
$ docker rmi myapp:v1
Untagged: myapp:v1
To completely remove the image layer, you must explicitly target the IMAGE ID:
$ docker rmi abc123def456
Untagged: myapp:latest
Untagged: company/myapp:v1
Deleted: sha256:abc123def456...
This will untag the image from all repositories and delete the underlying layer.
Saving and Loading Docker Images
In some cases, you may want to remove images from your local machine to free up space but still keep them around for future use. Two commands let you save images to tar files and load them back later: docker save
and docker load
.
To save an image:
$ docker save myimage:latest > myimage.tar
Then, to remove it:
$ docker rmi myimage:latest
And later, load it back in when needed:
$ docker load < myimage.tar
This can be handy for keeping base images you use for builds even if you don‘t always actively need them in your daemon.
Conclusion
We covered a lot! To recap:
- Remove individual images with
docker rmi
and containers withdocker rm
- Clean up unsed images and containers in bulk with
docker system prune
- Target image IDs to fully remove shared layers across multiple tags
- Incorporate container clean up into automated build pipelines
- Avoid using the
--rm
argument todocker run
- Save images to files if you need to remove them temporarily
Taking the time to prune your Docker environment will keep it lean and efficient. Working with a streamlined set of images and containers makes development and debugging easier in the long run. I encourage you to set up periodic Docker clean up on your development machines and build servers. Your future self will thank you!