Docker Compose exec variable interpolation

Running exec with Docker Compose is awesome. However, I can’t get it to interpolate environment variables correctly? This won’t work:

docker-compose exec mysql mysqldump --single-transaction -hlocalhost -uroot -p$MYSQL_ROOT_PASSWORD $DB_NAME > /tmp/mysqldump.sql

But if I bash into the container and run the following it works:

mysqldump --single-transaction -hlocalhost -uroot -p$MYSQL_ROOT_PASSWORD $DB_NAME > /tmp/mysqldump.sql

What am I doing wrong?

Have you tried putting single quotes around your exec? What you’re running into is the host is interpreting the variables before passing them in, and only your container has those variables in the environment.

docker-compose exec 'mysql mysqldump --single-transaction -hlocalhost -uroot -p$MYSQL_ROOT_PASSWORD $DB_NAME' > /tmp/mysqldump.sql (move the quotes to after the sql file if you intended to dump inside your container)

Thanks! That’s exactly right: the host is interpreting the variables before passing them in.

The single quotes worked, but not exactly as you suggested. Instead, I needed to execute it via sh -c. Turns out the official mysql Dockerfile in Docker Hub suggests this. Also, this Stack Overflow answer.

The final command:

docker-compose exec mysql sh -c 'exec mysqldump --single-transaction -hlocalhost -uroot -p$MYSQL_ROOT_PASSWORD $DB_NAME' > /tmp/mysqldump.sql