Introduction
Even Docker needs a bit of TLC sometimes — Tender Love and Care.
Mine had been through too many builds, abandoned containers, and half-finished experiments.
One day, docker builder prune -af just… never ended. Then docker info froze. My Mac sounded like a jet.
If your Docker Desktop ever behaves like an overworked pet — refusing to prune, restarting endlessly, or hoarding gigabytes of build cache — don’t panic.
Here’s how I nursed mine back to health, step by step, and how you can too.
🔎 Common Symptoms and What They Mean
| Symptom | Likely Cause | Quick Fix |
|---|---|---|
docker builder prune -af never ends |
BuildKit daemon frozen | Disable BuildKit and prune again |
docker info hangs |
Docker backend crashed | Restart Docker Desktop or kill com.docker.backend |
| Docker Desktop stuck on “Starting…” | Corrupted VM image (Docker.raw) |
Rename and recreate it |
| Disk space shrinking mysteriously | Old build cache or unused volumes | docker system df -v + prune |
| Builds suddenly slower | Build cache purged or misconfigured | Recreate builder and enable BuildKit |
| Containers stop randomly | Out of space in the VM | Free disk or expand disk image in settings |
🧠 Why Docker Freezes
Docker Desktop on macOS runs everything inside a Linux VM.
When that little VM becomes grumpy (or full), it misbehaves:
- BuildKit stalls: cache deletion loops forever
- Disk full: pruning can’t free space because deletions stall
- Zombie helpers:
vpnkitorcom.docker.backendlinger - Corrupted cache metadata: build state gone wrong
- Low disk headroom:
Docker.rawgasping for space
🧩 Fix Checklist
1️⃣ Restart Docker Desktop
Open Troubleshoot → Restart Docker Desktop
If that fails, select Clean / Purge build cache only.
2️⃣ Disable BuildKit temporarily
DOCKER_BUILDKIT=0 docker builder prune -af
3️⃣ Hard restart the backend
osascript -e 'quit app "Docker"'
sudo pkill -9 -f com.docker
sudo pkill -9 -f vpnkit
open -a Docker
4️⃣ Check disk space
df -h /
ls -lh ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw
docker system df -v
5️⃣ Recreate the builder (safe)
docker buildx rm default || true
docker buildx create --name default --use --driver docker-container
docker buildx inspect --bootstrap
6️⃣ Clean up caches
docker buildx prune -af --reserved-space 2GB
docker system prune -af --volumes
(Docker renamed --keep-storage to --reserved-space a while back — same idea: keep up to that much cache, prune the rest.)
7️⃣ Reclaim disk space from Docker Desktop
Start with Settings → Troubleshoot → Reclaim Disk Space. If that doesn’t shift the needle, trigger it from the terminal instead:
docker run --privileged --pid=host docker/desktop-reclaim-space
Only as a last resort — and only from the terminal, never by dragging things around in Finder, which is how Docker Desktop loses track of the file entirely — rename the VM disk and let Docker recreate it:
mv ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw \
~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw.bak
open -a Docker
🧮 Reading docker system df Like a Doctor
docker system df -v
Sample output:
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 12 3 6.23GB 3.1GB (50%)
Containers 4 3 480MB 0B (0%)
Local Volumes 7 5 1.2GB 220MB (18%)
Build Cache 382 0 75.4GB 75.4GB (100%)
Interpretation:
- Images → your actual builds and pulls
- Containers → running/stopped apps
- Local Volumes → persistent data (databases, uploads)
- Build Cache → temporary layers — safe to prune
- Reclaimable → what pruning would actually free — Build Cache sits at 100% reclaimable almost by definition, since nothing holds a reference to old cache entries once the image is built
If Build Cache is huge (>10 GB), it’s time for cleanup.
⚙️ Automating the Cleanup
After freeing 75.47 GB of cache, I automated it with a weekly script instead of remembering to babysit Docker myself.
🧾 File: ~/bin/prune-weekly.sh
#!/usr/bin/env bash
set -euo pipefail
echo "[$(date)] Starting weekly Docker cleanup…"
docker buildx prune -af --reserved-space 2GB
docker system prune -f # no --volumes: leave running apps' data alone
echo "[$(date)] Done. Current disk usage:"
docker system df
Make it executable (chmod +x ~/bin/prune-weekly.sh), then hook it up with a launchd job (macOS’s native scheduler) or a plain weekly cron entry:
# crontab -e — runs every Sunday at 03:00
0 3 * * 0 ~/bin/prune-weekly.sh >> ~/Library/Logs/docker-prune.log 2>&1
🧱 Safe for Running Apps?
Yes — it’s gentle. Your running Compose apps stay safe; only unused layers and stopped containers go. For total safety, replace:
docker system prune -af
with:
docker system prune -f
to keep all volumes intact.
🧩 Docker Compose Essentials
If you’re like me, you sometimes forget the exact commands, so here’s a pocket guide:
🔨 Build or rebuild
docker compose build
docker compose build --no-cache
docker compose up --build -d
🚀 Start / stop / restart
docker compose up -d
docker compose stop
docker compose restart
docker compose down
♻️ Full rebuild cycle
docker compose down --volumes --remove-orphans
docker compose build --no-cache
docker compose up -d
🧾 Logs & debugging
docker compose logs -f
docker compose logs -f web
docker compose exec api bash
docker compose cp web:/app/logs ./logs
🧰 Monitoring
docker ps
docker stats
docker top <container>
🔧 Handy Docker Commands
| Command | Purpose | Safe while running? |
|---|---|---|
docker ps |
List running containers | ✅ |
docker system df -v |
Show disk usage | ✅ |
docker builder prune -af |
Remove build cache | ✅ |
docker buildx prune -af --reserved-space 2GB |
Trim BuildKit cache | ✅ |
docker system prune -af |
Remove unused data | ⚠️ |
docker volume ls |
List volumes | ✅ |
docker volume prune |
Remove unused volumes | ⚠️ |
docker compose up -d |
Start services | ✅ |
docker compose down |
Stop & remove | ⚠️ |
docker compose logs -f |
Watch logs | ✅ |
docker compose exec web bash |
Debug container | ✅ |
docker image ls |
List images | ✅ |
docker image prune -af |
Remove dangling images | ✅ |
docker network prune |
Remove unused networks | ✅ |
🌿 Preventive Practices
- Keep a tidy
.dockerignore(skipvenv/,.git/,node_modules/, etc.) - Keep BuildKit ON (
Settings → Build → Use BuildKit) - Run
docker buildx pruneweekly or use the script above -
Monitor VM size:
ls -lh ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw - Avoid giving Docker more CPU/RAM than needed
- Update Docker Desktop regularly — each version gets better at cleaning up after itself
💬 Final Thoughts
Docker is like a brilliant but messy flatmate — builds incredible things, but never cleans the kitchen. Giving it a little TLC every week keeps your Mac fast, your mind calm, and your containers happier.
If Docker ever refuses to start or prune again, just whisper:
“It’s okay, you just need some TLC.”
And then follow this guide. 🩵
Did you like this post? Please let me know if you have any comments or suggestions.
Python posts that might be interesting for youStay Ahead in AI, Machine Learning & Python
No hype. Weekly notes on AI tools, Python, and what I'm actually building — plus six free gifts, including the 15-page Fantastic AI: The 2026 Toolkit and a Git Commands & Contribution Workflow Cheatsheet.
You're in
Check your inbox for Set a password to unlock articles if you want gated tutorials. Log in with the same email.