Docker / Xcode

The monthly dev cleanup: Docker, Xcode and simulators in one pass

Published Aug 25, 2026 · 6 min read · macoptimize

A development Mac fills up from four places in a predictable order: Docker, Xcode, simulators and Android. Each one grows without a cap and none of them cleans up after itself. This is the routine we run once a month, in the order that gives the biggest return first.

Step 1: find out where the space is

df -h /
du -sh ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw 2>/dev/null
du -sh ~/Library/Developer/Xcode/DerivedData
du -sh ~/Library/Developer/CoreSimulator
du -sh ~/.android ~/.gradle 2>/dev/null

Four lines, and you know which of the four systems is the problem this month. On our test machine the answer was 41GB of Docker, 23GB of Xcode output and 12GB of simulators, which is exactly the shape of most developer laptops.

Step 2: Docker, the safe part

docker system df
docker system prune -a

This clears stopped containers, unused networks, dangling images and build cache. Add --volumes only if you are certain no named volume holds anything you need, because that flag is the one that removes data rather than cache.

Then check whether the file on disk actually shrank:

du -h ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw

If it did not, and you need the space, resize the disk image in Docker Desktop under Settings, then Resources. That deletes everything inside Docker, so treat it as a last resort and back up volumes first.

Step 3: Xcode output

rm -rf ~/Library/Developer/Xcode/DerivedData/*
rm -rf ~/Library/Developer/Xcode/iOS\ DeviceSupport/*

Both are rebuildable. Quit Xcode first. Expect the next build of each project to be a full build, and expect DeviceSupport to refill the next time you attach a physical device.

Also worth checking are old archives, which are the builds you shipped to the App Store:

du -sh ~/Library/Developer/Xcode/Archives/* | sort -hr | head

Archives are the one folder in that tree you should keep deliberately. Each contains the dSYMs needed to symbolicate crash reports from a released build, so delete the versions you no longer support rather than all of them.

Step 4: simulators and runtimes

xcrun simctl delete unavailable
xcrun simctl list devices | grep -i unavailable

The first command removes devices whose runtime is gone. The second shows you what is left. For runtimes themselves, open Xcode Settings and remove the iOS versions you no longer test against, which is often 10GB or more.

Step 5: Android, if you build for it

du -sh ~/.gradle ~/.android/avd
./gradlew --stop
rm -rf ~/.gradle/caches/transforms-3

Gradle caches and emulator images are the two big offenders. Delete emulators you have not booted in a month from Android Studio's Device Manager rather than by hand, and back up your signing keys before touching anything inside ~/.android.

Running this in macoptimize

Steps 2 to 5 exist as checkboxes. A scan returns one screen with Developer, Browser and System totals, and the Developer group shows each source separately, so you can clear Xcode output without touching Docker volumes. The History tab then gives you a dated line per run showing how much came back.

Step 6: confirm the space returned

df -h /

Compare against step 1. If the number did not move as much as the tool claimed, you have hit the sparse file problem described above, and the fix is a disk image resize rather than more pruning.

Two habits keep this low effort: run it on the first working day of the month, and keep the output of df -h somewhere you will see it. A machine that recovers 60GB a month has a growth rate worth watching.

Where the space usually is, before you start

On a Mac used for iOS or cross platform work, one of these is almost always the answer, and the order is predictable:

LocationTypical holdTime to reclaim
Docker.raw20GB to 120GB5 minutes with a rebuild
Xcode DerivedData15GB to 80GBSeconds after quitting Xcode
iOS DeviceSupport10GB to 40GBSeconds
Simulator devices and runtimes5GB to 60GB2 minutes
Gradle and Android caches5GB to 40GB1 minute
Archives5GB to 50GBDecide carefully, not a cache

Order matters, and this is the order

Start with the tool that holds the most and costs the least to lose. Docker is usually that tool, because images rebuild from a registry and volumes are often disposable in development. Xcode comes next, because build output is free to delete once the editor is closed. Simulators after that, since they recreate themselves. Archives last, and only after reading the warning below.

The reason to follow an order at all is that free space on APFS is not always instant. Purges, snapshot thinning and background work can take minutes to show up in Finder, so confirm each step rather than assuming it failed.

Confirm the space actually returned

df -h /

Run it before and after each step and write the numbers down. Two things make the result confusing: local Time Machine snapshots can hold deleted data for up to 24 hours, and a build or index rebuild running in the background can consume space while you are clearing it. Give the machine two minutes of quiet between steps.

Turning this into a monthly habit

The cleanup is only useful if it repeats. A workable routine on the first Monday of each month:

  • docker system df, then docker builder prune, then a trim or a rebuild if the image is oversized.
  • Quit Xcode, delete DerivedData, delete old DeviceSupport folders.
  • xcrun simctl delete unavailable, and remove runtimes you never boot.
  • Run ./gradlew clean in the Android projects you are not testing right now, and prune the Gradle cache.
  • df -h / and compare with last month.

Fifteen minutes of work, once a month, and the disk stops being a source of surprises. If the routine is the part you know you will skip, macoptimize runs the scan on demand and shows each group with its real size, so the decision takes a click rather than a checklist.

FAQ

How long does this take?

First run is usually 15 to 30 minutes, most of it spent waiting for Docker to rebuild its disk image and for Xcode to release its files. The monthly version is closer to 10 minutes, and the only slow step is whatever Docker decides to re-pull.

Will my next builds be slower?

The first one will. Xcode does a full build instead of an incremental one, Docker re-pulls images on first use, and Gradle re-downloads dependencies. After that, everything returns to normal speed and the caches rebuild themselves as you work.

Can I automate it?

The safe parts, yes. A launchd agent or a cron entry that runs simctl delete unavailable and prunes Docker weekly is low risk. Automating DerivedData deletion is also reasonable if you can guarantee Xcode is closed. Automating the disk image rebuild is not, because losing images mid work is a bad surprise.

Is it safe to delete Xcode Archives as part of this routine?

Do not treat them as part of the routine. Archives hold shipping builds and the dSYM files used to read crash reports. Move old dSYMs somewhere durable first, then delete the archives they came from, and never remove an archive for a version still live on the store.

What if free space does not change after a cleanup?

Check for local Time Machine snapshots first, then wait two minutes and measure again. APFS can hold deleted blocks for a while and background indexing eats space in the meantime. If the numbers still have not moved, use df rather than Finder, since Finder rounds and caches its numbers.

Or let it do the work

macoptimize scans the folders in this guide, shows the real sizes, and clears what you select. $20 one time, covers 2 Macs.