Blog Developer 12 min read

Why Docker Desktop eats your Mac's disk, and how to get it back

You pruned your images, yet Finder still shows Docker using 60 GB. You are not imagining it, and nothing is broken. Docker on a Mac works in a way that makes this inevitable, and once you see the shape of it, reclaiming the space is three commands.

The short version

  • Docker on a Mac runs Linux in a virtual machine. Everything lives in one big disk image file, Docker.raw.
  • That file grows as you build and pull, and historically did not shrink when you deleted things inside it.
  • docker system df shows what is reclaimable. docker system prune -a --volumes clears it.
  • On current Docker Desktop the host file shrinks within seconds after pruning. Named volumes with your data are left alone.

The thing nobody tells you about Docker on a Mac

Docker runs Linux containers, and your Mac is not Linux. So Docker Desktop quietly runs a small Linux virtual machine, and everything, every image, container, volume and scrap of build cache, lives inside that VM. Crucially, the VM's entire disk is a single file on your Mac: Docker.raw, tucked away in ~/Library/Containers/com.docker.docker/Data/vms/0/data/.

Docker's own documentation says it plainly: Docker Desktop "stores Linux containers and images in a single, large disk image file in the Mac filesystem." That one design choice explains every strange thing you have noticed about Docker and disk space.

Docker images, containers, volumes and build cache all live inside one Docker.raw disk image file on the Mac. macOS APFS disk Docker.raw — one file, the whole Linux VM disk Images + dangling Containers Build cache Volumes your data
One file holds everything. Deleting an image frees space inside the file, but the file itself has to be told to shrink.

Why pruning did not seem to work

Here is the subtlety. When you run docker rmi or docker system prune, you free space inside the VM. But the Docker.raw file on your Mac does not automatically shrink to match. Docker's docs are explicit: "Space is not freed automatically when files are deleted inside running containers," and "space is only freed when images are deleted." For years this meant the file grew and grew and essentially never came back without a reset.

There is a second trap. If you check the file with ls -lh, you see its maximum logical size, not how much it actually uses, because it is a sparse file. To see real usage, use du:

# real physical size of the Docker disk image (not ls -lh)
$ du -h ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw

See what is actually in there

Before deleting anything, look. docker system df breaks the usage into images, containers, local volumes and build cache, and tells you how much of each is reclaimable.

$ docker system df

TYPE            TOTAL   ACTIVE   SIZE      RECLAIMABLE
Images          23      4        18.4 GB   14.9 GB (80%)
Containers      9       2        1.1 GB    820 MB (72%)
Local Volumes   14      3        9.6 GB    6.2 GB (64%)
Build Cache     201     0        11.3 GB   11.3 GB (100%)

Two things usually dominate that reclaimable column. The first is dangling images: every time you rebuild a tagged image, the previous layers are orphaned and show up as <none>:<none>. The second is build cache, which BuildKit accumulates continuously and is almost always 100 percent reclaimable.

Reclaim it, step by step

The blunt instrument is docker system prune. By default it removes stopped containers, unused networks, dangling images and unused build cache: all rebuildable, all safe. Add -a to also remove tagged images you are not currently using, and --volumes to clear unused anonymous volumes.

# safe default: stopped containers, dangling images, unused build cache
$ docker system prune

# aggressive: also unused tagged images and anonymous volumes
$ docker system prune -a --volumes

# or target just the usual suspects
$ docker image prune        # dangling images
$ docker builder prune -a    # all build cache
Mind your volumes

Docker never auto-removes volumes, "because to do so could destroy data." A named volume is where your database and other persistent data live, and the default prune leaves those alone. Only --volumes removes unused anonymous volumes. Before running the aggressive form, glance at docker volume ls and make sure nothing you care about is sitting in an anonymous volume.

Getting the space back to macOS

Pruning frees space inside the VM. On modern Docker Desktop, reclaiming it on the Mac side is now fast: with the current .raw disk format the host space "should be reclaimed within a few seconds" after you prune. If it does not, there is an explicit reclaim step, and as a last resort you can shrink the maximum size in Settings or use Troubleshoot to clean or purge all data (which recreates a fresh, empty image).

# nudge host reclamation if the file hasn't shrunk
$ docker run --privileged --pid=host docker/desktop-reclaim-space

# confirm on the Mac side
$ du -h ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw
To be precise

"Docker does not auto-shrink" is true for the host file, not the whole story. Pruning genuinely frees blocks inside the VM; it is only the handback to macOS that is not automatic. Since Docker Desktop 4.20 and the .raw format, that handback is quick, so do not assume reclamation is impossible, just that it needs a nudge.

The OrbStack contrast

If this whole dance annoys you, it is worth knowing it is a Docker Desktop design choice, not a law of nature. OrbStack, a drop-in alternative that runs the same Docker CLI, uses a sparse disk that "automatically shrinks when you delete data." A fresh install is under 10 MB, and it manages the disk fully dynamically. If Docker's disk behaviour has burned you repeatedly, OrbStack is the usual recommendation, though its data lives in a different place (under a Group Containers folder) and the exact path is worth confirming on your version.

A reliable routine

  1. Run docker system df to see what is reclaimable.
  2. Glance at docker volume ls so you do not prune data you want.
  3. Run docker system prune (or -a --volumes if you have reviewed).
  4. Check du -h on Docker.raw; if it did not shrink, run the reclaim container.

Done every few weeks, this keeps Docker from quietly reclaiming tens of gigabytes of your disk. Real-world reports of Docker images sitting at 40, 60, even 100 GB are not rare; they are just what happens when build cache and dangling layers are never swept up.

Docker space, read live and labelled

StorageSage reads Docker directly, separates dangling images, build cache and orphaned volumes, and flags Compose projects whose folder is gone. Because Docker removes these itself rather than via the Trash, StorageSage tells you that up front before anything is freed.

Download for macOS

Sources

  • Docker — macOS FAQ (single disk image, space not freed automatically, reclaim step); docker system df, docker system prune, docker image prune, docker builder prune and volume pruning reference.
  • OrbStack — FAQ and efficiency documentation (auto-shrinking sparse disk).
  • Docker issue tracker and engineering write-ups documenting real-world disk-image ballooning.

Keep reading