You open System Settings → General → Storage on your Mac and see the dreaded label: "System Data: 98 GB". You haven't downloaded movies, and your Downloads folder is empty. Yet your 512GB SSD is choking.
If you are a developer on macOS, the primary suspect is almost certainly Docker Desktop.
Even with just a few containers or a local Postgres instance, Docker on macOS silently hoards 30GB to 80GB of disk space. Worse: when you delete containers or images inside Docker, macOS doesn't automatically get that disk space back.
In this guide, we'll dissect Docker Desktop's storage architecture on macOS, explain why the virtual disk never shrinks on its own, and provide Terminal commands to reclaim your space.
1. Why Docker on macOS is Fundamentally Different
On Linux, Docker runs natively against the host kernel using cgroups and overlay filesystems (overlay2). Files write directly to /var/lib/docker on your host drive.
macOS, however, uses the Darwin kernel with no native Linux container primitives. To run containers, Docker Desktop spins up a lightweight Linux virtual machine via Apple's Hypervisor framework.
┌────────────────────────────────────────────────────────┐
│ macOS Host (APFS Filesystem) │
│ ~/Library/Containers/com.docker.docker/Data/vms/... │
│ └── 📁 Docker.raw (Virtual Disk Image: 64 GB) │
│ ▲ │
│ ▼ [Block-level virtualized disk] │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Linux VM (ext4 Filesystem) │ │
│ │ /var/lib/docker/ (overlay2, buildkit, volumes) │ │
│ └──────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────┘
Everything inside Docker—container layers, pulled images, BuildKit caches, and volume mounts—is packed into a single virtual disk file on your host drive named Docker.raw (or Docker.qcow2).
2. Locating Docker.raw on APFS
The virtual disk image is typically located at:
~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw
The APFS Sparse File Trap: Apparent vs. Physical Size
If you check the file with ls -lh:
ls -lh ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw
You might see 64G. However, Docker.raw is an APFS sparse file; it only allocates physical blocks on your SSD as data is written. To see how much physical space it actually consumes, use du:
du -sh ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw
If du -sh reports 38G, Docker is actively taking 38 GB of physical flash storage.
3. Why Docker's Virtual Disk Never Shrinks
Here is the fundamental architectural trap with docker mac storage:
- When you run
docker buildor pull an image, Linux writes blocks into the virtual disk. - The APFS host sees new blocks written and expands the physical footprint of
Docker.raw. - Later, you run
docker rmor delete an old project. The Linux VM marks those sectors as free within itsext4filesystem. - However, APFS on macOS has no automatic way of knowing that those blocks were freed inside the Linux VM.
Unless an explicit TRIM/DISCARD command is passed down through the virtual block device driver to APFS, the host file stays bloated at its peak high-water mark. Your Mac SSD thinks that space is occupied, even if 80% of Docker's internal filesystem is empty air.
4. Diagnosing Docker Bloat from the Terminal
Before touching anything, let’s see what is actually consuming space inside Docker's virtual disk. Run:
docker system df
You will see output similar to this:
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 18 4 12.4GB 8.6GB (69%)
Containers 8 2 840MB 620MB (73%)
Local Volumes 14 3 14.2GB 11.1GB (78%)
Build Cache 142 0 18.9GB 18.9GB (100%)
Notice that Build Cache and Local Volumes often represent the vast majority of bloat!
For a granular breakdown of every individual container, image layer, and volume:
docker system df -v
5. The Step-by-Step Reclamation Guide
Let's methodically reclaim this space, from the safest non-destructive steps to deep pruning.
Step 1: Purge the BuildKit Cache (The Biggest Hidden Hog)
Modern Docker builds use BuildKit by default. BuildKit aggressively caches intermediate compilation layers, npm installs, and apt packages so future builds are fast. But over months of active development, this cache routinely balloons past 20GB.
To reclaim the build cache:
docker builder prune -f
To purge all build cache, including non-dangling build stages:
docker builder prune -a -f
[!TIP]
This does not delete any running containers or active project images. It only clears build cache layers. The next time you build an image from scratch, Docker will simply re-download or re-compile missing layers.
Step 2: Remove Dangling and Unused Images
When you rebuild a Dockerfile with the same tag (e.g. myapp:latest), the previous image build becomes an untagged <none>:<none> dangling image.
To delete dangling images:
docker image prune -f
To delete all images not currently linked to a running container:
docker image prune -a -f
Step 3: Remove Stopped Containers
Every time you docker run without the --rm flag, the container's read-write filesystem overlay remains on disk when it exits:
docker container prune -f
Step 4: Audit Dangling Volumes
Anonymous volumes created by database containers (Postgres, Redis, MongoDB) are persistent by design. If you discard a test container without removing its volume (docker run -v /data), that volume remains forever:
# List orphaned volumes not attached to any container
docker volume ls -qf dangling=true
# Remove dangling volumes safely
docker volume prune -f
[!WARNING]
If you have a local dev database in an anonymous volume that isn't named, pruning volumes will wipe that database! Ensure active databases are backed up or defined with named volumes before runningvolume prune.
6. Docker Cleanup Strategy Matrix
Here is how the different Docker commands compare in terms of disk savings and safety:
| Command | What It Cleans | Typical Savings | Safety Level | Risk / Impact |
|---|---|---|---|---|
docker builder prune -a |
BuildKit compilation cache | 10 GB – 25 GB | 🟢 High | Slower initial rebuild for your next docker build
|
docker image prune |
Untagged dangling images (<none>) |
2 GB – 10 GB | 🟢 High | Zero impact; unreferenced layers only |
docker container prune |
Stopped containers | 1 GB – 5 GB | 🟡 Medium | Removes logs and ephemeral writable layer of exited containers |
docker volume prune |
Dangling anonymous volumes | 5 GB – 30 GB | 🟠 Moderate | Discards orphaned volume data; protect dev databases first |
docker system prune -a --volumes |
Everything not actively running | 25 GB – 70 GB | 🔴 Aggressive | Wipes all unused images, caches, stopped containers, and volumes |
7. Shrinking Docker.raw on APFS
After pruning internally, ensure host APFS actually reclaims the space.
Method A: Docker Desktop Compact
Docker Desktop (v4.20+) includes a native disk compaction utility:
- Open Docker Desktop settings.
- Go to Settings → Resources → Advanced (or the Troubleshoot bug icon).
- Select "Clean / Purge data" or click "Compact virtual disk".
Method B: Resetting the Virtual Disk
If Docker.raw remains stubbornly large, reset it cleanly:
killall Docker
rm -f ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw
When restarted, Docker initializes a fresh virtual disk of just ~1.5 GB.
8. Automated Intelligence: Dusty's Docker Overlay Detection
If auditing sparse files and BuildKit layers manually is tedious, Dusty handles it automatically.
Dusty is an AI-powered macOS storage cleaner built in native Swift for developers.
How Dusty Handles Docker Storage:
-
Docker VM & Overlay Detection: Automatically pinpoints
Docker.raw, displaying true physical usage vs logical size. - Google Gemini AI Explanations: Explains obscure cache layers and overlay paths in plain English before cleanup.
- Trash-First Safety: Files move to macOS Trash rather than permanent deletion.
-
Developer Bloat Scanning: Simultaneously clears orphaned
node_modules, XcodeDerivedData, and WhatsApp media. - Transparent Pricing: $9.99 lifetime license (pay once, own forever) with a 24-hour free trial. No subscriptions.
Quick Install via Homebrew:
brew install sarmadhussainch/dusty/dusty
GitHub Tap: github.com/sarmadhussainch/homebrew-dusty
Official site: dustystorage.com
Final Thoughts
Docker Desktop is essential for modern development, but on macOS, its storage footprint demands vigilance. Audit docker system df monthly and prune your BuildKit cache to keep your SSD fast and healthy.
What About Your Machine?
How much space was Docker.raw taking on your Mac? Did clearing BuildKit make the biggest difference? Share your numbers in the comments!

Top comments (0)