← All articles

Docker Says It's Empty. Docker.raw Is 60 GB. Here's Why.

Docker Desktop on macOS stores everything in one growing VM disk image that never shrinks on its own. Why `docker system prune` appears to do nothing, and how to actually get the space back.

DockermacOSStorageDeveloperCache

You ran docker system prune -a. It reported reclaiming 40 GB. Your Mac has exactly as much free space as before.

This is the single most confusing storage problem on a developer’s Mac, and it is not a bug.

Why it happens

Docker containers are a Linux technology. macOS is not Linux, so Docker Desktop runs a Linux virtual machine, and everything — images, layers, containers, volumes, build cache — lives inside that VM’s filesystem.

That filesystem is one large file on your Mac, usually named Docker.raw.

When you delete an image, Docker frees space inside the VM’s filesystem. The blocks become available for the VM to reuse. But the file on your Mac that contains that filesystem does not shrink, for the same reason deleting files inside a .dmg does not make the .dmg smaller.

So Docker.raw only ever grows. Pull a 3 GB image, delete it, pull another 3 GB image, and the file is 6 GB even though Docker honestly reports 3 GB in use.

Confirm it on your machine

What Docker thinks:

docker system df

What is actually on disk — find the file rather than guessing the path, because it has moved between Docker Desktop versions:

find ~/Library/Containers/com.docker.docker -name "*.raw" -exec du -sh {} \; 2>/dev/null

On most installs that lands in ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw, but do not hardcode it — check.

A gap between the two numbers is the space you are looking for.

du versus Finder. On APFS the image file is sparse, so du reports blocks actually allocated while Finder shows the logical size. du is the number that matters — it is the space you cannot use for anything else.

Step 1: clean inside the VM first

Nothing else works until the space is free inside the filesystem.

# What is safe to remove, itemised
docker system df -v

# Dangling images and stopped containers only — conservative
docker system prune

# Everything not currently used by a running container
docker system prune -a

# Same, plus unused named volumes
docker system prune -a --volumes

Read this before running the last one. --volumes removes unused named volumes, which is where local development databases live. If you have a Postgres container whose data you care about and it is not running right now, that data is inside a named volume, and this deletes it. Check first:

docker volume ls

The build cache is usually the biggest single item and is always safe to drop — it only makes the next build slower:

docker builder prune -a

Step 2: actually shrink the file

Now the space is free inside the VM but the file is still huge. Options, best first:

Let Docker Desktop reclaim it

Recent Docker Desktop versions can return unused blocks to macOS automatically, and the settings pane exposes a manual trigger. Open Docker Desktop → Settings → Resources → Advanced and look for a disk usage section with a reclaim or clean-up control. This is the safe path and it preserves everything you have not pruned.

Restart Docker Desktop

Some versions compact the image during a clean shutdown and restart. Quit Docker Desktop fully — from the menu bar, not just closing the window — wait, and start it again. Then re-measure. It is free to try.

The nuclear option

Settings → Troubleshoot → Reset to factory defaults (older versions: “Clean / Purge data”) deletes Docker.raw outright and recreates it empty. You get every gigabyte back immediately.

You also lose everything: all images, all containers, all volumes, all build cache. Everything re-pulls from registries and rebuilds from Dockerfiles, so for most development setups the real cost is bandwidth and one slow afternoon. But if a container holds the only copy of some data, back it up first:

docker run --rm -v my_volume:/data -v "$PWD":/backup alpine \
  tar czf /backup/my_volume.tar.gz -C /data .

Stop it recurring

Cap the disk image. In Settings → Resources, the virtual disk limit is a hard ceiling. Set it to something you can live with — 64 GB is plenty for most work — and Docker cannot silently consume 200 GB. This is the highest-value five seconds in this article.

Prune on a schedule. A weekly docker system prune -a is a reasonable habit, or a fortnightly docker builder prune -a if you build large images often.

Use multi-stage builds. Every intermediate layer of a naive Dockerfile is stored. Multi-stage builds discard the build environment and keep only the final artefact, which shrinks both what you push and what you store.

Consider an alternative runtime. OrbStack and Colima both run Docker workloads on macOS with more conservative disk behaviour. OrbStack in particular reclaims space back to the host as you go, which sidesteps this entire article. Colima keeps its own disk image under ~/.colima — check that too if you use it:

du -sh ~/.colima 2>/dev/null

The general lesson

Every macOS tool that runs a Linux VM has this shape: a file that grows and does not shrink, with an in-VM view that disagrees with your Mac’s view. Docker is simply the one most developers hit.

DevCruft shows the image file at its true on-disk size alongside everything else on your Mac, so the gap between “Docker says 4 GB” and “this file is 61 GB” is visible instead of something you have to go looking for.

More sources of the same problem: the full developer storage guide.

Or let the map do it.

DevCruft finds every cache in this article, shows you what each one costs you, and clears them in one click.

Apple silicon & Intel · No account · Nothing leaves your Mac