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.

env var demo

While I initially wrote this to help with Octobox setup, Octobox actually implements most of these steps already in their docker-compose.yml file. 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"

environment node

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  

.env file

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.yml so you can jump straight to adding your .env file!

Summary

So in summary to provide environment variables to a container you can:

  1. Include KEY=value pairs in the command line right before calling docker-compose
  2. Include them as an environment node for any service in your docker-compose.yml
  3. Add them to a .env file and reference them using ${KEY} syntax in your docker-compose.yml file
  4. 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.

Comments

comments powered by Disqus