Using Variables in Docker Compose files
Introduction
I was recently helping a friend set up Octobox and noticed they very handily provide a pre-built docker-compose.yml file for Docker Compose users! Octobox (as with many other Dockerized apps) uses environment variables for configuration, so the docker-compose command looks like this:
GITHUB_CLIENT_ID=yourclientid GITHUB_CLIENT_SECRET=yourclientsecret docker-compose up --build
For those unfamiliar with it, the GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET before the command are declaring environment variables for docker-compose.
While I initially wrote this to help with Octobox setup, Octobox actually implements most of these steps already in their
docker-compose.ymlfile. If you're setting up Octobox, skip down to "Going one better"; otherwise, read on!
Declare your environment with your app
But you don't want to have to remember those env vars every time you bring the application up, so let's get those out of the command line. In your docker-compose.yml for any service node, you can add an environment key and include environment variables and their values in that:
services:
app:
image: ...
environment:
- VAR_NAME=value
- FOO="bar"
In the case of Octobox, the variables are already included, but other apps may not include them for you. For our Octobox configuration, we could replace the existing values in our docker-compose.yml under the app service:
services:
app:
. . . #snipped
environment:
- GITHUB_CLIENT_ID=yourclientid
- GITHUB_CLIENT_SECRET=yourclientsecret
and we would simply run docker-compose up as before and our environment variables would be captured and available inside the container.
Going one better
We can do one better than that! Having now included our id and secret in our docker-compose.yml file, we must protect it very carefully, and we can't commit the file back to source control! However, since everything should be in source control and your InfoSec team would prefer your GitHub API keys weren't on the internet, there is an alternative: the .env file.
Beside your docker-compose.yml file, create a new text file called .env. In it, add the following:
CLIENT_ID=yourclientid
CLIENT_SECRET=yourclientsecret
Now, open your docker-compose.yml file again, and replace yourclientid with ${CLIENT_ID} and yourclientsecret with ${CLIENT_SECRET}. That is:
services:
app:
. . . #snipped
environment:
- GITHUB_CLIENT_ID=${CLIENT_ID}
- GITHUB_CLIENT_SECRET=${CLIENT_SECRET}
Now, when you run docker-compose up, Docker will resolve the ${NAME} variables to values from your .env file. Now you can safely commit your docker-compose.yml file without leaking your creds (as long as you don't commit the .env file!).
Octobox includes the variables pre-declared in their provided
docker-compose.ymlso you can jump straight to adding your.envfile!
Summary
So in summary to provide environment variables to a container you can:
- Include
KEY=valuepairs in the command line right before callingdocker-compose - Include them as an
environmentnode for any service in yourdocker-compose.yml - Add them to a
.envfile and reference them using${KEY}syntax in yourdocker-compose.ymlfile - Mix and match any of the above!
Personally I always include non-sensitive variables using method 2 (i.e. as an environment node under the service), but include sensitive data/secrets as variables in a .env file (which I add to .gitignore to prevent accidental checkins).
Note that what I've described here is only scratching the surface of how you can use environment variables in Docker (both directly and with Compose). Check out the full documentation for all the different methods available.
How do you manage your environment variables with Docker Compose? Let me know in the comments or on Twitter.