Cleanup & Maintenance
#Cleanup & Maintenance
After this lesson you'll know:
- how to analyze and free disk space
- what docker system prune really does (and doesn't)
- how to automate Docker cleanup
- which tools exist for image analysis
#The Docker Garbage Problem
Docker accumulates garbage over time:
- Stopped containers ā after every
docker runwithout--rm - Unused images ā old versions after
docker build - Orphaned volumes ā forgotten data after
docker rm -v - Build cache ā can grow to gigabytes after a few weeks
If you never clean up, you'll eventually hit a full disk ā and Docker will refuse to pull new images.
#Analyze First: docker system df
Before you delete, analyze:
# Overview
docker system df
# TYPE TOTAL ACTIVE SIZE RECLAIMABLE
# Images 12 5 2.345GB 1.2GB (51%)
# Containers 8 3 45MB 25MB (55%)
# Local Volumes 6 2 890MB 680MB (76%)
# Build Cache - - 420MB 420MB (100%)
# Detailed view with layers (very revealing!)
docker system df -v
# Shows every image, container, and volume individually
docker system df is your first step when you run into disk space issues. It tells you exactly where the waste is.
š” The RECLAIMABLE column is gold. That's the space you can free immediately by cleaning up.
#The Big Gun: docker system prune
# The nuke (CAUTION!)
docker system prune -a --volumes
# This deletes: all stopped containers, unused images,
# all volumes without a running container, build cache
# ā ļø Volumes with important data will be deleted! Only use --volumes
# when you're sure all volumes are expendable.
The safe way ā start without --volumes:
docker system prune -a --filter "until=24h"
# Only deletes things older than 24h. Great for weekly routines.
The --filter parameter is gold. It lets you only delete what's truly old ā keeping today's images safe.
#Targeted Cleanup (the safe way)
# Stopped containers only
docker container prune
# Unused images only (older than 24h)
docker image prune -a --filter "until=24h"
# Orphaned volumes only
docker volume prune
# Build cache only (safe ā gets rebuilt)
docker builder prune
# Keep certain images (delete all except postgres or nginx)
docker image prune -a --filter "reference!=postgres" --filter "reference!=nginx"
#Automated Cleanup with Cron
Why clean manually when your computer can do it?
# Once a week, Sunday at 3 AM
# crontab -e:
0 3 * * 0 docker system prune -af --filter "until=24h" >/dev/null 2>&1
# Once a month also volumes (careful ā only if no critical data stored)
0 4 1 * * docker system prune -af --volumes --filter "until=168h" >/dev/null 2>&1
With --filter "until=24h" you ensure freshly built images aren't deleted. Perfect for CI servers or dev machines.
Docker built-in log rotation:
# Start Docker with limited logs (in daemon.json)
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
Without this config, a few weeks of container logs can fill your disk. A container logging 100 lines/second writes ~30 GB per week. With rotation to 3Ć10 MB, it's capped at 30 MB.
#Image Size Analysis
# All images with sizes
docker images
# Layer-by-layer analysis of a specific image
docker history my-app:latest
# IMAGE CREATED CREATED BY SIZE
# abc123 2 min ago COPY . . 2.5MB
# def456 2 min ago RUN npm run build 245MB
# ghi789 3 min ago COPY --from=builder /app/dist ./dist 1.2MB
# ...
# Layer sizes only
docker history --no-trunc my-app | awk '{print $1, $NF}'
docker history shows every layer with its size. This is the secret weapon to identify oversized images: "Why is my image 500 MB? Because RUN npm install installed all devDependencies and I never cleaned up the layer."
External tool: [dive](https://github.com/wagoodman/dive) ā analyzes image layers interactively.
dive my-app:latest
# Shows layer contents + space waste directly
#Keeping Build Cache Under Control
# Check cache size
docker builder prune --all --keep-storage 2GB 2>/dev/null; docker system df | grep Build
# Limit cache to 2 GB (during prune)
docker builder prune --all --keep-storage 2GB
# Or globally in /etc/docker/daemon.json
{
"builder": {
"gc": {
"enabled": true,
"keepStorage": "2GB",
"defaultKeepStorage": "200MB"
}
}
}
# Complete build cache wipe (for CI/systemd timers)
docker builder prune -af
The build cache is the biggest hidden space hog. Especially on CI servers or when you build regularly. The global config limits it permanently ā set it once, forget it.
#Checklist: Survival Routine
- Daily:
docker system dfā a quick glance is enough - Weekly:
docker image prune -a --filter "until=24h"ā old builds gone - Monthly:
docker volume pruneā orphaned volumes - As needed:
docker builder pruneā when cache gets too large - One-time: Enable log rotation in
/etc/docker/daemon.json
#ā Try it out
docker system dfā show how much space Docker is using. Also try-vdocker image prune -a --filter "until=24h"ā delete only old unused imagesdocker history alpine:latestā inspect the layers of a slim image (only ~7 MB!)docker builder prune --all --keep-storage 500MBā cap cache at 500 MB
#š Summary
- docker system df before deleting ā analyzing is half the job
- --filter 'until=24h' makes prune safe for daily use
- Log rotation in daemon.json prevents full disks from logs
- Build cache can eat gigabytes ā builder prune keeps it in check
- Automated cleanup via cron = set it once, forget it