Elena' s AI Blog

My Docker Needed Some TLC

17 Sep 2026 (updated: 16 Sep 2026) / 9 minutes to read

Elena Daehnhardt

Docker pruning and rebuilding — image credit: Elena


TL;DR:
  • Docker reliability on macOS improves with cache hygiene, VM disk monitoring, and deterministic recovery playbooks.

📚 This post is part of the "MLOps & Deployment" series

Series: MLOps & Deployment (Part 1 of 10)

Previous: Part 5 — Caching Docker Compose Builds with BuildKit

Next: Part 2 — Docker Permissions Without Panic: Why I Ran chown Inside My Container

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: vpnkit or com.docker.backend linger
  • Corrupted cache metadata: build state gone wrong
  • Low disk headroom: Docker.raw gasping 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 (skip venv/, .git/, node_modules/, etc.)
  • Keep BuildKit ON (Settings → Build → Use BuildKit)
  • Run docker buildx prune weekly 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 you



desktop bg dark

About Elena

Elena, a PhD in Computer Science, simplifies AI concepts and helps you use machine learning.





Citation
Elena Daehnhardt. (2026) 'My Docker Needed Some TLC', daehnhardt.com, 17 September 2026. Available at: https://daehnhardt.com/blog/2026/09/17/my-docker-needed-some-tlc/
All Posts