Docker prune on Mac: How to remove unused containers, images, and volumes

5 min read

Searching for useful tips on how to run docker system prune? When your Docker builds keep failing, or your Docker Desktop’s virtual disk is red, or du -sh /var/lib/docker returns a painful number, you need to get to work quickly.

Docker doesn’t clean up on its own. Stopped containers, all dangling image layers, even unused networks, and build cache all stay on disk until you actively remove them.

Docker prune

Before you delete anything, you should check what Docker is going to remove with:

  • docker system df

Terminal running docker system df command to check disk usage

This is going to show you all the disk usage by images, containers, local volumes, and build cache, giving you a better idea of where the space is actually being used.

Then you can use the standard safe cleanup with:

  • docker system prune

You’ll need to type y to continue.

Good to know: when running this kind of prune, you can expect this to clean up any stopped containers, unused networks, any dangling images, and unused build cache. But it won’t remove any active, running containers, or any images currently used by containers, or volumes.

The docker system prune flags

Flag

Function

-a / --all

Removes all unused images. Including tagged images that are not currently used by a container. It’s pretty drastic for image cache because you’ll need to re-pull or rebuild anything you need later.

--volumes

Includes unused anonymous volumes in the cleanup.

-f / --force

Skips the confirmation prompt. I'd save this for scripts, CI jobs, or scheduled cleanup where there’s no one there to type y.

--filter

Narrows the cleanup by age or label, such as until=<duration> or label=<key>=<value>.

 

This is the total wipe-out command, but use it with proper caution:

  • docker system prune -a --volumes -f

Terminal running docker system prune force command without confirmation

On developer machines, I think this is quite risky; it’ll remove unused tagged images and anonymous volumes without asking for confirmation.

Targeted pruning

I think targeted prune commands work well, they let you clean the part of Docker that’s actually taking up space, without jumping straight to docker system prune -a --volumes

Terminal command pruning all unused Docker images and volumes

  • If you want to remove stopped containers only, use: docker container prune

  • Get rid of dangling images with: docker image prune (add -a for all unused)

  • If you’re trying to remove anonymous unused volumes, use: docker volume prune (add --all to include named)

  • To remove your unused networks, use: docker network prune

  • If you want to clear build cache, use: docker builder prune

  • And finally, to get rid of Buildx build cache, use: docker buildx prune

In general, this is better for shared machines or mixed environments, and dev setups.

Use filtering to remove old data

I use the until filter a lot because it lets you remove objects older than a set time; just run:

  • docker image prune -a --filter "until=168h"

Terminal command removing Docker images older than one week

(The 168h is, of course, adjustable, or add a timestamp.)

For a nice little routine cleanup, use:

  • docker image prune -a -f --filter "until=72h"

That’s going to remove unused images older than three days, but keeps newer builds in place. Adding a label can remove stopped containers unless they have the keep label; use:

  • docker container prune --filter "label!=keep"

Never prune these

  • Any named volumes that contain app data (Think about databases, even uploads, queues, or any local test records). I’d always back them up before removing anything with docker volume rm

  • Images you built locally but haven’t pushed to a registry -a, Docker can remove unused tagged images too.

  • Volumes attached to stopped but important containers.

I tend to think docker system df -v is a safer option, and not to state the obvious, but always review first what Docker is holding onto, because Docker prune is irreversible; there’s no undo button or easy recovery path.

It’s not just Docker

Docker system prune only cleans Docker’s own unused objects. On macOS and Windows, don’t forget that Docker Desktop stores Docker data inside a virtual disk, and pruning the files inside doesn’t guarantee space frees up instantly. If you feel like your cleanup efforts have gone unrewarded, I’d first check Docker Desktop itself.

Go to Docker Desktop > Settings > Resources to review the virtual disk size. You can also use Docker Desktop’s Clean / Purge Data or Reset to factory defaults options, but only after backing up anything important.

On a busy dev Mac, any of these caches can add up too:

  • ~/Library/Caches/Homebrew

  • ~/.npm

  • ~/Library/Developer/Xcode/DerivedData

  • ~/.gradle/caches

  • ~/Library/Caches/pip

MacPaw’s CleanMyMac CLI, which is still a public beta, can sweep all of this in one go. You can install it with: brew install --cask macpaw/taps/cleanmymac-cli

Then I’d start off with:

  • cleanmymac clean dev

CleanMyMac dev cleanup scan results showing Homebrew cache files found

This covers everything from Docker, Homebrew, npm, Yarn, pnpm, pip, Cargo, Xcode, VS Code, JetBrains, and other developer-tool caches. You can also run an inspection with:

  • cleanmymac analyze

CleanMyMac disk analysis showing storage breakdown by system folder

Automatic Docker cleanup options

For weekly cleanup on Mac or Linux, this command runs every Sunday at 3 a.m. and removes unused images older than seven days. First, you’ll need to open your crontab with: crontab -e

And add: 0 3 * * 0 /usr/local/bin/docker system prune -a -f --filter "until=168h" >> /var/log/docker-prune.log 2>&1

Note: on Apple Silicon Macs, replace /usr/local/bin/docker with /opt/homebrew/bin/docker

Avoid automating --volumes unless you're 100% sure that no apps are storing data in anonymous volumes.

Troubleshooting tips

  • Docker Desktop virtual disk

Pruning inside Docker doesn’t always reduce the actual host-side virtual disk.

  • Running containers

Images used by running containers are skipped. You have to stop the container first.

  • Build cache

You can try the docker builder prune or docker buildx prune commands to target these.

  • Linux permissions

If you get permission errors, your user may not be in the docker group. Run this first: docker system df -v