Docker Maintenance & Disk Reclamation
Continuous development and automated CI/CD deployments quickly accumulate gigabytes of dangling image layers, orphaned anonymous volumes, and dormant BuildKit caches. Without regular hygiene, host disks eventually hit 100% capacity. In this chapter, learn how to audit disk consumption with docker system df, perform safe filtered purges, and schedule automated maintenance.
1. Auditing Docker Disk Space: docker system df
Before deleting anything, inspect where disk space is being allocated across the four Docker subsystems:
# Overview summary across images, containers, local volumes, and build cache:
docker system df
# Verbose breakdown showing size and reclaimable percentage per item:
docker system df -v| Resource Type | Description | Reclaimable Criteria |
|---|---|---|
| Images | Read-only OCI image layers stored in /var/lib/docker/overlay2/. | Any image not referenced by a currently existing container. |
| Containers | Writable ephemeral container layers and stdout/stderr JSON logs. | Any container in the exited or stopped state. |
| Local Volumes | Stateful directories stored in /var/lib/docker/volumes/. | Any volume not mounted by a currently active or stopped container. |
| Build Cache | BuildKit execution cache stages stored in /var/lib/docker/buildkit/. | Intermediate compilation stages no longer needed for current builds. |
2. Dangling Images vs Unused Images
Dangling Images (<none>:<none>)
Occurs when you build an updated version of an image with an existing tag (e.g. api:v1). Docker assigns the tag to the new image, leaving the older layers untagged as <none>. These are 100% safe to delete immediately:
docker image prune
Unused Images (-a Flag)
Images that possess valid tags (like postgres:16-alpine), but are not actively used by any running or stopped container. Deleting them reclaims massive space, but requires re-downloading layers next time:
docker image prune -a
3. Safe Time-Filtered Pruning
Avoid blindly running prune -a on production servers, as it purges recently cached layers that speed up daily builds. Use time-based filters (e.g. until=168h for 7 days):
# 1. Purge unused images older than 7 days (168 hours):
docker image prune -a --filter "until=168h" -f
# 2. Reclaim BuildKit compilation cache older than 48 hours:
docker builder prune --filter "until=48h" -f
# 3. Purge stopped containers older than 24 hours:
docker container prune --filter "until=24h" -f4. The Nuclear Prune & The Volume Warning
Extreme Caution: The --volumes Flag
When you execute docker system prune -a --volumes, Docker deletes EVERY UNMOUNTED VOLUMEon the host machine. If you previously stopped your production database container for maintenance, its attached named volume will be permanently destroyed along with all persistent database data!
Automated Server Maintenance Cron Job
Schedule a weekly automated cleanup job in /etc/cron.weekly/docker-cleanup that reclaims disk space safely without endangering database volumes:
#!/bin/bash
# /etc/cron.weekly/docker-cleanup
# Safely reclaim dangling layers, old build caches, and stopped containers older than 14 days
/usr/bin/docker container prune -f --filter "until=336h"
/usr/bin/docker image prune -f --filter "until=336h"
/usr/bin/docker builder prune -f --filter "until=168h"
/usr/bin/docker network prune -fNext Up: Container Orchestration & Kubernetes
In Chapter 20, discover when single-node Docker is enough and when your architecture needs to graduate to Kubernetes or Docker Swarm.
Chapter 20: Docker vs Kubernetes →