compose: docker-compose run --rm does not remove volumes

Running one-off commands with docker-compose does not delete volumes used by the container. This is different than docker run --rm which does remove volumes after the container is deleted.

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Reactions: 7
  • Comments: 17

Commits related to this issue

Most upvoted comments

This is a fundamental docker behaviour - if the image has volumes in it, they will created whenever you run a container from that image.

It’s common to run one off tasks from an image that has volumes you may never use for that task.

The docker-compose run --rm behaviour should mirror the docker run --rm behaviour, which does correctly remove volumes.

You can work around this issue in Docker Compose 1.7 as follows:

docker-compose run xxx docker-compose down -v

The key here is to not use the --rm flag on the run command. Because Docker Compose 1.7 removes containers started with the run command, it cleans up everything correctly including all volumes (as long as you use -v)

@schmunk42

docker-compose down -v always removes named local volumes (1.6+), the current issue relates to volumes defined in the image of the service you are running that are automatically created not declared as explicit volumes in your docker-compose.yml.

For example given the following docker-compose.yml file:

version: '2'

volumes:
  mysql_run:
    driver: local

services:
  db:
    image: mysql:5.6
    volumes:
      - mysql_run:/var/run/mysqld

If we use docker-compose run --rm:

$ docker volume ls
DRIVER              VOLUME NAME
$ docker-compose run --rm db
Creating volume "tmp_mysql_run" with local driver
error: database is uninitialized and password option is not specified
  You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD
$ docker-compose down -v
Removing network tmp_default
Removing volume tmp_mysql_run
$ docker volume ls
DRIVER              VOLUME NAME
local               a79c78267ed6907afb3e6fc5d4877c160b3723551f499a3da15b13b685523c69

Notice that the volume tmp_mysql_run is created and destroyed correctly, but we get an orphaned volume which is the /var/lib/mysql volume in the mysql image.

If we use docker-compose run instead:

$ docker volume ls
DRIVER              VOLUME NAME
$ docker-compose run db
Creating volume "tmp_mysql_run" with local driver
error: database is uninitialized and password option is not specified
  You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD
$ docker-compose down -v
Removing tmp_db_run_1 ... done
Removing network tmp_default
Removing volume tmp_mysql_run
$ docker volume ls
DRIVER              VOLUME NAME

Everything is cleaned up correctly…

docker-compose down -v would bring down the service stack and delete named volumes. I want neither to happen.

@dnephin Our use-case is a rather simple web-app. We usually have web (nginx), php and worker (same image as php). We’re sharing static-files (assets) between web and php, but in other scenarios we also need to share files between php and worker.

The volume is defined in docker-compose.yml - sure there could be optimizations how much files are shared, but it still looks like a general problem to me.

docker exec could be a workaround, but I’d like to stay with docker-compose and I would rather not rely on the fact that my container is named project_php_1 because it may be named project_php_2 in some cases.

I also noticed that we ran a cleanup script before, I had to reactivate/fix that, but having an option to remove volumes after docker-compose run would still be great.

I need to look into named volumes a bit more I think, basically all apps we run, are running on a swarm, so I need to configure that properly.