`docker compose down --volumes` Is the Cleanup Command You Need When Stale State Keeps Surviving Between Runs
A practical guide to `docker compose down --volumes` for developers who keep thinking they reset their local stack when old database rows, cache entries, or bad seed data are still haunting every rerun.
Why this command matters: the bug is not always in your code. Sometimes the bug is old state pretending to be fresh.
Compose-based development is convenient right up until it trains you to say, "I already restarted everything," when what you actually restarted was only the containers. Named volumes often survive that restart. When they do, so do old rows, stale caches, half-applied migrations, and corrupted local state that keeps poisoning every new run.
That is why docker compose down --volumes matters.
The command
docker compose down --volumesThis removes:
- the Compose-managed containers
- the default networks created for the project
- the named volumes declared for the project
That third item is the real headline. It is what turns a routine stop/start into an actual environment reset.
Why normal restart often lies to you
A lot of people do this:
docker compose down
docker compose upThen they wonder why:
- old users still exist in the database
- the cache still contains yesterday's junk
- a broken migration state keeps reappearing
- startup scripts behave as if nothing was reset
The answer is usually simple: your data volume never went away.
When you should reach for it
This command is especially useful when:
- local DB state is suspect
- a search index looks poisoned
- seed data keeps colliding with new tests
- you need to reproduce a first-run onboarding path
- a teammate says "works on my machine" and you want the machine to forget things
Common examples include Postgres, MySQL, Redis, Meilisearch, Elasticsearch, MinIO, and any app that writes state to a mounted named volume.
What to do before using it
This is the part impatient developers skip: confirm whether the volume contains anything you care about.
If the answer is yes, export or back it up first.
For example, if your database matters:
docker compose exec db pg_dump -U postgres appdb > backup.sqlor for MySQL:
docker compose exec db mysqldump -u root -p appdb > backup.sqlThe reason to be careful is simple: down --volumes is powerful precisely because it is destructive.
A practical clean-reset loop
When local state is suspicious, this sequence is often more useful than endless tinkering:
docker compose down --volumes
docker compose pull
docker compose up --buildThat gives you:
- fresh containers
- fresh networks
- fresh named volumes
- rebuilt images if your app changed
Now if the same bug appears, you have a much stronger case that the problem is in the app, config, or image rather than leftover state.
Common mistake: using it too casually
Do not turn down --volumes into a reflex. If your project depends on valuable local state, blowing it away every time you feel uncertain is sloppy. Use it deliberately when stale persisted data is a plausible cause, not as an emotional support command.
Final recommendation
If your Compose stack keeps behaving like history never dies, stop focusing only on containers. docker compose down --volumes is often the command that finally resets the state you thought you had already reset.