Docker Compose lets you run multi-container Docker applications. If you want to use Docker Compose with environment variables, you have several options. The official documentation is a good reference, but it's hard to understand and very abstract!
Let's take a practical look at how to pass environment variables to your Docker containers using Docker Compose.
We'll use a simplified version of the official getting started Docker Compose app, which is a basic web application built with Python and Flask, but you'll be able to use the same method to access environment variables using any other programming language.
Setting up the example project
If you want to follow along, clone our Example Docker Compose Project. You'll also need Docker and Docker Compose installed on your machine.
We'll assume that you want to pass an environment variable called SECRET_ENV to your application.
The project consists of:
- An app.py file that returns a string containing the SECRET_ENV value.
- A Dockerfile that starts up the Flask app.
- A Docker Compose that defines the variable and starts the Dockerfile.
A requirements.txt file that installs the Flask framework.
Defining the environment variable in the Docker Compose file
The easiest way to send an environment variable to your Docker app is by defining it using an environment: section in your docker-compose.yml file as in the example below:
If you do this, run docker compose build && docker compose up, and visit http://localhost:8000 in your web browser. You'll see the variable displayed.
This is easy, but not very useful. If you don't want to have the variable in your application code, you probably don't want it in your docker-compose.yml file either.
Passing an environment variable from the host
Press Ctrl + C twice to stop the Docker server and edit the docker-compose.yml file to look as follows:
Save the file and run export HOST_SECRET=my_secret_from_host in your shell. This sets the environment variable on your host machine, which will be read by the docker-compose.yml file after you rebuild with Compose.
Now run docker compose build && docker compose up again.
Visit http://localhost:8000 in your browser and you'll see that the app now displays the new secret variable.
Passing an environment variable from a .env file
If you have a lot of environment variables or you want to be sure you don't lose them, you can define them in a file called .env in the same directory as your docker-compose.yml file.
Quit your shell to clear the HOST_SECRET variable that you set before and open a new shell. Create a file called .env containing the following:
Save the file and run docker compose build && docker compose up again.
Now you'll see the variable as you defined it in your .env file. Usually, you would add this file to .gitignore and recreate it on each machine you run the code on, which means that your (sensitive) environment variables are not stored with your codebase.
Understanding the priority of environment variables
If you define the same variable in a .env file and directly in your environment (for example, using export HOST_SECRET=my_secret_from_host), Docker Compose will give priority to your environment. The variable in your .env file will be ignored.
If you want to check exactly what is being used by your docker-compose.yml file without building the whole project, you can run:
docker compose convert
This will output the model it uses, based on your docker-compose.yml file but with any environment variables replaced with their real values. If you run it now, you'll see it still picks up the value from the .env file.
If you run export HOST_SECRET=my_secret_from_host and docker compose convert again, you'll see it prefers the variable you set explicitly over the one in the .env file.
The best way to handle environment variables in your Docker Compose projects
To recap, you can:
- Hard code your variables directly in your docker-compose.yml.
- Pull the variables from the host environment.
- Define the variables in a .env file.
For non-sensitive variables that don't change very often, it's easiest to simply put the values directly in the docker-compose.yml file. This means you don't have to spend extra time and effort tracking down the values and messing around with multiple files.
For sensitive values, such as database passwords and API tokens, you should ideally only define these directly in secure environments (for example, your production server). However, it's inconvenient to lose all of these values every time you need to restart your server or change to a new machine.
Therefore a good tradeoff between security and convenience is to use a .env file containing your sensitive environment variables. It's important to keep any copies of this file in a secure place, such as a secrets manager or vault, and to not check in this file as part of your code base.
Managing environment variables and secrets with ReleaseHub
If you're looking for a simple and powerful platform to manage all of your environments for you, take a look at Release. Using our custom application template file, you can easily set environment variables and map them to specific environments, ensuring that your secret management is both secure and convenient.
Release is the simplest way to spin up even the most complicated environments. We specialize in taking your complicated application and data and making reproducible environments on-demand.