You ran docker volume rm and got slapped with volume is in use. Or maybe you're trying to clean up disk space and aren't sure which prune command actually removes named volumes. Either way, this guide covers all four scenarios — simple removal, Compose teardown, bulk pruning, and the frustrating case where Docker insists a volume is in use even though docker ps -a shows nothing.
Always Backup Important Data First
Removing Docker volumes is permanent and cannot be undone. Before executing any volume removal commands, backup critical data. This can cause permanent data loss if volumes contain production databases or essential files.
Before removing anything, confirm the exact volume name and check how much space volumes are consuming:
bash
# List all volumes
docker volume ls# Check disk usage per volume
docker system df -v
docker system df -v is the fastest way to see which volumes are taking up space, so you know what's worth cleaning up before you start removing things.
Method 1: Simple Removal
If a volume isn't attached to any container (running or stopped), this is all you need:
bash
docker volume rm VOLUME_NAME
You can also remove multiple volumes in one command:
Error response from daemon: remove VOLUME_NAME: volume is in use - [CONTAINER_ID]
Method 2: Docker Compose Projects (docker compose down -v)
If the volume was created as part of a Docker Compose project, docker volume rm is the wrong tool. Use docker compose down from the project directory instead.
To stop and remove containers, networks, and volumes for a Compose project:
bash
docker compose down -v
# or
docker compose down --volumes
What -v actually removes
The --volumes / -v flag removes both named volumes declared in the volumes: section of your Compose file and anonymous volumes attached to containers. Without -v, docker compose down leaves all volumes intact.
If you've changed volume names in your Compose file and docker volume rm still fails, you may have orphaned containers still holding references to the old volumes. Clean those up with:
bash
docker compose down --volumes --remove-orphans
--remove-orphans removes containers for services that are no longer defined in the Compose file — a common cause of ghost volume references.
Method 3: docker volume prune (Bulk Cleanup)
To remove all unused anonymous volumes at once:
bash
docker volume prune
Add -f to skip the confirmation prompt:
bash
docker volume prune -f
Important: By default, docker volume prune only removes anonymous volumes (those not explicitly named in your Compose file or docker run command). To also remove unused named volumes, add --all:
bash
docker volume prune --all
You can also target volumes by label if you've labelled them in your Compose file:
docker volume prune vs docker system prune --volumes
These two commands are NOT equivalent:
docker system prune --volumes removes only anonymous unused volumes (plus stopped containers, unused networks, and dangling images).
docker volume prune removes anonymous unused volumes by default; add --all to include named volumes too.
If you want to clean everything — containers, networks, images, and anonymous volumes — use docker system prune --volumes. If you specifically need unused named volumes gone, use docker volume prune --all.
Method 4: "Volume is in Use" But No Containers Running
This is the most frustrating Docker volume scenario. You see:
code
Error response from daemon: remove VOLUME_NAME: volume is in use - [CONTAINER_ID]
...but docker ps -a shows nothing. Here's why it happens and how to fix it.
Why this happens
Docker tracks volume references using in-memory reference counting. A few things can leave that counter stale:
Stopped containers still holding references — a stopped container is not the same as a removed container. Until you docker rm it, it still references any volumes it was using.
Compose orphan containers — changing volume names in a Compose file can leave old containers that reference the previous volume names.
Docker daemon reference count bug — in rare cases the in-memory counter doesn't update cleanly when a container is removed, leaving a ghost reference.
Docker Desktop extensions — extensions can own volumes with no visible container in docker ps -a.
Important: docker volume rm --force does NOT fix this
The -f / --force flag on docker volume rm is commonly misunderstood. It does not allow you to remove a volume that's in use. It only suppresses errors if the volume has already been removed (a race-condition helper). The in-use check is never bypassed.
Step-by-step diagnostic flow
Step 1 — Confirm no stopped containers exist
bash
docker ps -a
docker ps (without -a) only shows running containers. Always use -a to see stopped ones. If you see containers there, remove them:
bash
docker rm CONTAINER_ID
# or remove all stopped containers at once
docker container prune
Then retry docker volume rm VOLUME_NAME.
Step 2 — If it was a Compose project, clean up properly
bash
docker compose down --volumes --remove-orphans
Run this from the directory containing your compose.yaml. This removes containers (including orphans), networks, and volumes for the project.
Step 3 — Restart the Docker daemon
If volumes still report as in use after removing all containers, the daemon's reference count is stale. A restart clears it:
bash
# Linuxsudo systemctl restart docker
# Docker Desktop (Mac / Windows)# Use the Restart option from the tray icon menu
Then retry:
bash
docker volume rm VOLUME_NAME
Step 4 — Check for Docker Desktop extension volumes
If you're on Docker Desktop and the volume name contains docker-extension (e.g. mochoa_pgadmin4-docker-extension-desktop-extension_pgadmin_data), the volume is owned by a Docker Desktop extension — not a regular container. It won't show up in docker ps -a.
Fix: open Docker Desktop → Extensions → find and uninstall the extension that owns the volume. Then retry docker volume rm.
Step 5 — Last resort: full prune
bash
docker system prune
This removes all stopped containers, unused networks, and dangling images. After this, any remaining in-use ghost references should be gone and docker volume rm should succeed.
Best Practices
Use Named Volumes in Production
Always use explicitly named volumes for production environments instead of anonymous volumes. This makes volume management easier, prevents accidental removal during prune operations, and makes it obvious what data lives where.
Always backup before removing. For a complete walkthrough on migrating Docker volumes between servers, check the Docker migration guide.
bash
# Backup a volume's data to a tar archive
docker run --rm -v VOLUME_NAME:/source -v $(pwd):/backup alpine tar -czf /backup/volume-backup.tar.gz -C /source .
Use named volumes in production for easier management.
yaml
# In docker-compose.ymlvolumes:my_database_data:name:my_project_database_data
Document volume dependencies within your application.
Prefix with sudo: sudo docker volume rm VOLUME_NAME
Summary
List volumes with docker volume ls and check disk usage with docker system df -v before removing anything.
Simple removal: docker volume rm VOLUME_NAME — works only when no container references the volume.
Compose projects: docker compose down -v removes containers, networks, and both named and anonymous volumes for the project. Add --remove-orphans if volume names have changed.
Bulk cleanup: docker volume prune removes unused anonymous volumes; docker volume prune --all also removes unused named volumes. These are not the same as docker system prune --volumes.
"Volume is in use" with no containers: check for stopped containers, run docker compose down --volumes --remove-orphans for Compose projects, restart the Docker daemon, or check for Docker Desktop extension volumes.
Next step: if you need to move volumes to a new server, the Docker container migration guide walks through the full backup and restore process.