Picture this: You’re working on your latest project, everything’s running smoothly, and suddenly your system starts crawling. A quick check reveals the culprit - your disk is nearly full, and Docker is the main suspect. Sound familiar?
If you’ve been using Docker for a while, you’ve probably encountered this frustrating scenario. Docker has a tendency to accumulate images, containers, volumes, and networks over time, quietly consuming gigabytes of precious disk space. What starts as a few hundred megabytes can quickly balloon into tens of gigabytes without you even noticing.
The good news? This is a common problem with straightforward solutions. In this post, I’ll walk you through practical strategies to reclaim your disk space and prevent Docker from becoming a storage hog in the future.
Understanding What’s Taking Up Space
Before diving into solutions, let’s understand what Docker stores and where your disk space is actually going.
Docker stores several types of data:
- Images: The base templates for your containers
- Containers: Running or stopped instances of images
- Volumes: Persistent data storage for containers
- Build cache: Intermediate layers from building images
- Networks: Virtual networks for container communication
The biggest space consumers are typically unused images and the build cache, especially if you’re frequently building custom images or pulling different versions for testing.
Quick Diagnosis: Check Your Docker Disk Usage
First, let’s see exactly what’s consuming your space:
$ docker system dfThis command gives you a breakdown of Docker’s disk usage:
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 15 5 2.1GB 1.8GB (85%)
Containers 8 2 45MB 32MB (71%)
Local Volumes 3 1 1.2GB 800MB (66%)
Build Cache 25 0 1.5GB 1.5GB (100%)
Space used 4.8GB
Reclaimable 4.1GBThe “RECLAIMABLE” column shows you exactly how much space you can free up. In this example, we could reclaim over 4GB!
For more detailed information, add the verbose flag:
$ docker system df -vThe Nuclear Option: Clean Everything
If you’re in a hurry and don’t mind removing all unused Docker data, here’s the fastest solution:
$ docker system prune -a --volumesWarning: This command removes:
- All stopped containers
- All networks not used by at least one container
- All images without at least one container associated to them
- All build cache
- All volumes not used by at least one container
This is aggressive but effective. You’ll likely free up several gigabytes instantly.
Surgical Approach: Targeted Cleanup
If you need more control over what gets removed, here are targeted cleanup commands:
Remove Unused Images
# Remove dangling images (untagged images)
$ docker image prune
# Remove all unused images (not just dangling ones)
$ docker image prune -aClean Up Containers
# Remove all stopped containers
$ docker container prune
# Remove specific containers
$ docker rm $(docker ps -aq --filter status=exited)Clear Build Cache
The build cache often consumes the most space:
# Remove all build cache
$ docker builder prune
# Remove build cache older than 24 hours
$ docker builder prune --filter until=24hRemove Unused Volumes
# Remove all unused volumes
$ docker volume prune
# List volumes to see what you're working with
$ docker volume lsClean Up Networks
# Remove unused networks
$ docker network prunePreventing Future Disk Space Issues
Cleaning up is good, but prevention is better. Here are strategies to keep Docker from eating your disk space:
1. Regular Cleanup Automation
Create a simple cleanup script and run it weekly:
#!/bin/bash
# docker-cleanup.sh
echo "Starting Docker cleanup..."
# Remove stopped containers
docker container prune -f
# Remove unused images
docker image prune -f
# Remove unused volumes
docker volume prune -f
# Remove build cache older than 7 days
docker builder prune --filter until=168h -f
echo "Cleanup completed!"
docker system dfMake it executable and add it to your cron jobs:
$ chmod +x docker-cleanup.sh
$ crontab -e
# Add this line to run weekly:
0 2 * * 0 /path/to/docker-cleanup.sh2. Use Multi-Stage Builds
When building custom images, use multi-stage builds to reduce final image size:
# Build stage
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Production stage
FROM node:18-alpine
WORKDIR /app
COPY /app/dist ./dist
COPY /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/index.js"]3. Be Selective with Base Images
Choose smaller base images when possible:
# Instead of this (huge)
FROM ubuntu:latest
# Use this (much smaller)
FROM alpine:latest
# Or even better for Node.js apps
FROM node:18-alpine4. Use .dockerignore
Create a .dockerignore file to prevent unnecessary files from being included in your build context:
node_modules
npm-debug.log
.git
.gitignore
README.md
.env
.nyc_output
coverage
.DS_Store5. Limit Log File Sizes
Configure Docker to limit log file sizes:
# In daemon.json or docker-compose.yml
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}Advanced: Docker System Events
For ongoing monitoring, you can set up Docker system events to track what’s happening:
$ docker system events --filter type=container --filter event=createThis helps you understand which containers are being created most frequently and might be contributing to space issues.
Troubleshooting Common Issues
“No space left on device” errors
If you’re getting this error even after cleanup:
-
Check if Docker is using a different data directory:
$ docker info | grep "Docker Root Dir" -
Move Docker data to a larger partition if needed:
# Stop Docker daemon $ sudo systemctl stop docker # Move data directory $ sudo mv /var/lib/docker /new/location/docker # Update daemon.json $ sudo vim /etc/docker/daemon.json # Add: "data-root": "/new/location/docker" # Restart Docker $ sudo systemctl start docker
Images that won’t delete
Some images might be referenced by stopped containers:
# Force remove image
$ docker rmi -f image_id
# Or remove container first
$ docker rm container_id
$ docker rmi image_idMonitoring Your Progress
After implementing these strategies, monitor your Docker disk usage regularly:
# Create an alias for quick checking
$ echo 'alias docker-space="docker system df"' >> ~/.bashrc
$ source ~/.bashrc
# Now you can quickly check space usage
$ docker-spaceMy Personal Workflow
Here’s how I handle Docker disk space in my daily workflow:
- Weekly cleanup: Automated script removes unused resources
- Build optimization: Always use multi-stage builds and alpine images
- Regular monitoring: Quick
docker system dfcheck before starting new projects - Selective pulls: Only pull specific image tags, avoid
:latestwhen possible
This approach has kept my Docker disk usage under control while maintaining a smooth development experience.
Conclusion
Docker disk space issues are frustrating but entirely manageable with the right approach. The key is combining reactive cleanup with proactive prevention.
Start with a comprehensive cleanup using docker system prune -a --volumes to reclaim space immediately, then implement regular maintenance scripts and build optimization techniques to prevent future issues.
Remember, a few minutes of maintenance can save you hours of frustration and ensure your development environment runs smoothly. Your future self (and your disk drive) will thank you for establishing these habits early.