Practical Docker Habits for Real Teams
How to Clean Up Dangling Docker Images and Volumes Safely
A practical guide to removing dangling Docker images and unused volumes safely, with copy-ready cleanup commands and a reusable bash script.
Docker usually gets blamed when disks fill up, but the real problem is often just neglect. A few build experiments, old intermediate layers, stopped containers, orphaned networks, and forgotten volumes can quietly eat storage until every new docker build feels slower and every teammate starts wondering what is safe to delete.
The tricky part is not knowing that cleanup matters. The tricky part is knowing what can be removed safely and what might still hold useful data.
That distinction matters most for two categories:
- dangling images
- unused or orphaned volumes
This guide explains how to clean both up with confidence, when to be careful, and how to automate the routine with a copy-ready bash script.
What “dangling” means in Docker
Docker uses the word dangling in a narrower way than many teams expect.
A dangling image is usually an image layer or tagless image that is no longer referenced by a meaningful tag. These often appear after repeated builds where new layers replace old ones.
In practice, dangling images are often:
<none>images after rebuilds- leftover intermediate build results
- artifacts that are no longer part of the image name you actively use
That makes them a safer cleanup target than “all unused images,” which can still include older but intentionally kept versions.
Why volumes deserve more caution
Volumes are different because they often contain state that matters:
- database data
- cache contents
- uploaded files
- local development snapshots
- temporary pipeline outputs
A dangling image is usually clutter.
An unused volume might be clutter, but it might also be the only copy of something a container used last week.
That is why cleanup should be ordered:
- inspect what is taking space
- remove obviously safe clutter first
- only then remove unused volumes deliberately
Start by seeing what you actually have
Before deleting anything, check the current state:
docker image ls
docker volume ls
docker system df
docker system df is especially useful because it gives a quick summary of:
- image usage
- container usage
- local volumes
- build cache
That alone helps teams stop guessing.
The safest first cleanup commands
If you only want the safest easy win, start with dangling images:
docker image prune -f
This removes dangling images only.
For volumes, Docker is more conservative. A safer inspection-first path is:
docker volume ls
docker volume prune
The second command removes volumes that are not used by at least one container. Docker will prompt before deletion unless you add -f.
That is a useful guardrail, especially on development machines.
A more complete but still practical cleanup routine
On a typical local machine, the maintenance sequence often looks like:
docker container prune -f
docker image prune -f
docker network prune -f
docker volume prune -f
docker builder prune -f
This handles:
- stopped containers
- dangling images
- unused networks
- unused volumes
- old build cache
It is a strong maintenance routine for local development environments, but you should still understand one important difference:
image pruneonly removes safer dangling image clutter by defaultvolume prunecan remove real unused data
That is why some teams run image cleanup automatically but run volume cleanup more deliberately.
A copy-ready bash script for local cleanup
Here is a practical script you can copy, review, and run on your own machine:
#!/usr/bin/env bash
set -euo pipefail
echo "== Docker disk usage before cleanup =="
docker system df || true
echo
echo "== Dangling images =="
docker image ls -f dangling=true || true
echo
echo "== Unused volumes =="
docker volume ls -qf dangling=true || true
echo
read -r -p "Continue with safe local Docker cleanup? [y/N] " answer
if [[ ! "$answer" =~ ^[Yy]$ ]]; then
echo "Cleanup cancelled."
exit 0
fi
echo
echo "Removing stopped containers..."
docker container prune -f
echo
echo "Removing dangling images..."
docker image prune -f
echo
echo "Removing unused networks..."
docker network prune -f
echo
echo "Removing unused volumes..."
docker volume prune -f
echo
echo "Removing old build cache..."
docker builder prune -f
echo
echo "== Docker disk usage after cleanup =="
docker system df || true
echo
echo "Docker cleanup complete."
What this script gets right:
- it shows current usage before cleanup
- it previews dangling images and dangling volumes
- it asks for confirmation
- it targets local cleanup categories that are commonly safe
- it shows the after-state so the result is visible immediately
When not to run the full script blindly
Do not run cleanup casually when:
- your local Docker setup contains databases you have not backed up
- you are working with long-lived named volumes you still need
- another teammate relies on shared local state on the same machine
- you are troubleshooting a broken environment and still need the artifacts
This matters especially for Compose-based stacks. A local environment may look disposable, but named volumes often preserve the only convenient copy of:
- Postgres data
- Redis snapshots
- uploaded media
- temporary shared pipeline files
If you are actively designing or reviewing those stacks, a browser-side Docker Compose Builder & Validator is useful because it makes volume declarations easier to inspect before cleanup habits become dangerous.
Dangling versus unused: the distinction teams should keep
The easiest way to avoid accidental loss is to keep these categories separate in your head:
Dangling images
Usually safe to remove.
They are generally leftovers from builds and retagging workflows.
Unused volumes
Sometimes safe to remove, sometimes not.
They are safe only when you are sure no container still needs the data and no workflow depends on it later.
That distinction sounds simple, but it is the difference between reclaiming disk space and deleting useful state.
Why Compose users should inspect volume declarations first
Teams using Compose often forget that the cleanup decision starts in the YAML.
If a stack uses:
- named volumes for databases
- bind mounts for source code
- shared temp volumes between worker services
then cleanup risk changes immediately.
That is why Docker Compose Builder & Validator and YAML ↔ JSON Converter fit this workflow naturally. Compose files become easier to inspect when the structure is readable and the storage declarations are obvious.
A calmer maintenance habit for real developer machines
The best maintenance habit is not aggressive pruning. It is predictable pruning.
A good rule of thumb:
- clean dangling images regularly
- clean build cache when space pressure grows
- clean unused volumes only after inspection
That keeps local Docker environments healthier without making every cleanup session feel risky.
A practical weekly routine
For many developers, this is enough:
- run
docker system df - remove stopped containers
- prune dangling images
- prune old build cache
- inspect volumes before pruning them
That small routine prevents storage bloat from turning into a bigger incident later.
The takeaway
Cleaning up Docker safely is less about memorizing one magic command and more about separating clutter from state.
Dangling images are usually easy wins. Volumes deserve a second look.
If you keep that distinction clear and use a script with confirmation instead of blind deletion, Docker cleanup becomes routine instead of stressful.