Cleaning Up Docker
How to remove containers, images, volumes, and networks safely
When experimenting with Docker, or setting up new projects that require testing, you’ll quickly accumulate stopped containers, dangling images, and unused volumes. Cleaning them up is essential for saving disk space and avoiding confusion.
Containers
docker ps -a # list all containers
docker rm <id|name> # remove stopped container
docker container prune
Images
docker images
docker rmi <name/ID>
docker image prune -a
Volumes
docker volume ls
docker volume rm <name/ID>
docker volume prune
docker volume prune --all # remove all unused volumes, not just anonymous
Networks
docker network ls
docker network rm <name/ID>
docker network prune
👉 Be careful: removing a volume permanently deletes its data.
A Useful Habit To Keep Things Clean
You can help yourself by using the --rm flag. It’s an auto remove feature of docker run. It removes containers as soon as they’re stopped. It’s perfect for one-off commands and for testing.
docker run --rm node -p "'A JS String'"
# ← Prints “A JS String”
docker run --rm node -p "5+9*43"
# ← Prints “392”
# Run your script and remove the container
docker run --rm node myscript.js
In these examples, Docker starts the container, calls the command, prints the output and removes the container instantly. This avoids having to write an additional command to remove the container.
Removing More At Once
You can’t remove running containers without an additional flag. The extra flag tells Docker you know it’s running and your action is deliberate.
# Start a container and keep it running
docker run --name demo -d alpine sleep infinity
# Check that it’s running
docker ps -l
# ← Prints last running container
# Use `-f` to stop & remove
docker rm -f demo
# ← Prints “demo” if removed
You can remove a container and its anonymous volumes at the same time. Here we list current volumes, start a container with a new anonymous volume, and remove them both at the same time.
docker volume ls -q | wc -l
# ← Prints volume count
# Start a container and new anonymous volume
docker run --name demo -v /myvol -d alpine sleep infinity
# Check that it’s running
docker ps -l
# ← Prints last running container
docker volume ls -q | wc -l
# ← Previous volume count + 1
# Stop and remove container and volume
docker rm -f -v demo
# ← Prints “demo” if container removed
docker volume ls -q | wc -l
# ← Initial volume count
You cannot remove a container and its named volumes at the same time.
# Start a container and named volume
docker run --name demo -v my_volume_name:/myvol -d alpine sleep infinity
# Check that it’s running
docker ps -l
# ← Prints last running container
# Check volume
docker volume ls -q | grep my_volume_name
# ← Prints “my_volume_name”
# Try removing volume and container
docker rm -f -v demo
# ← Prints “demo” if container removed
docker volume ls -q | grep my_volume_name
# ← Still prints “my_volume_name” — not removed
Named volumes must be removed with docker volume rm <volume-name>.
Dangling vs Unused
Run this:
docker volume prune --help
Notice “Remove unused local volumes”.
The prune subcommand exists under docker image, docker volume, docker network, and docker system.
Without additional options, it removes dangling objects — usually anonymous or tagless.
-
Images
docker image prune→ removes dangling images (untagged).docker image prune --all→ removes all unused images, tagged or not.
-
Volumes
docker volume prune→ removes dangling volumes (anonymous-unused).docker volume prune --all→ removes all unused volumes, named and anonymous.
-
Networks
docker network prune→ removes all unused networks (never the built-ins).
-
System
docker system prune→ removes stopped containers, unused networks, dangling images, and unused build cache.docker system prune --all→ adds all unused images (not just dangling).docker system prune --all --volumes→ also removes all unused volumes (named + anonymous).
You can preview dangling objects with the dangling=true filter:
docker image ls --filter dangling=true
# ← Prints tagless images
docker volume ls --filter dangling=true
# ← Prints anonymous-unused volumes
# Works for networks too, but undocumented
docker network ls --filter dangling=true
# ← Prints unused networks (same as prune target)
Unfortunately, previewing --all isn’t possible.
But since most Docker objects are ephemeral in nature, it’s safe to remove almost everything. The main exception is volumes: once deleted, the data is gone unless you have backups. Using named volumes provides a bit more safety, but not much if you’re inattentive.
Key Terms
Dangling Image
An image without a tag, usually created when rebuilding with the same tag.
Prune
Docker’s term for bulk deletion of unused objects (containers, images, volumes, networks).
Anonymous Volume
A volume created without a name, tied only to the container that created it.