How to Access Environment Variables in Your docker-compose.yaml File

Daniel Pericich
4 min readJan 22, 2024
Photo by Brock Wegner on Unsplash

A critical part of building secure applications is ensuring sensitive data is protected and privileged. Items like API keys or secrets must be hidden from public view, and access limited to the least number of people. Whether it is application code or DevOps config files, we need ways to secure our sensitive data as best we can. In this article, we will look at how to use environment variables with docker-compose.yaml files to hide our secrets in shared repositories.

The Importance of Using an .env File for Sensitive Data

To protect our sensitive data, we need a way to separate our sensitive data from our code. One of the cardinal sins of programming OpSec is leaving secrets and keys hardcoded into code stored in shared repositories. If your team does this, you are vulnerable to malicious users who may access your repos.

To prevent data exposure, we place our secrets and keys in a separate file called a .env file. The .env file is a list of key-value pairs. Each key is an environment variable name. The value is the API key or secret. This file is stored locally in your root directory, and should never be pushed to a shared repository.

Figure 1. An example of a basic .env file with database credentials.

While this file is great for separating your keys and secrets from your code, it can require libraries or syntax to access these values in your code. If we want to access env variables in a Node project we will need to use a third-party library like dotenv. There are other ways to access the env variables if working with other file types like docker-compose files.

Creating a Basic docker-compose.yaml file for PostgreSQL Container

We want to create a container for our project to run a local instance of PostgreSQL. Of course, we could enter a command on the command line to create the container, but this is a lot of typing:

docker container run -d -p 5432:5432 --name postgres1 -e POSTGRES_PASSWORD=mypassword postgres

Looking at the docs on Dockerhub we can see that this container requires even more arguments than a simple nginx or Linux container. It requires a database password with additional options for setting the database user and other values. Even without specifying every value, this is still a lot to type.

To simplify this process, we can translate this command into a docker-compose.yaml file. These files let us run the simple command “docker compose up” to build and start a container.

If we translate the command to a compose file we end up with something like this:

Figure 2. Docker compose file for creating our PostgreSQL container.

This looks better, but we cannot push this to our project repo yet. We have plain text values where we define our database user and password. Anyone with access to this file now has the credentials for our database. We need a way to separate the values of these data secrets from our code.

Accessing Environmental Variables to Create a PostgreSQL Container

I mentioned that each language and framework can access .env variables slightly differently. Luckily, docker-compose files can access env variables from the .env file with simple string interpolation.

To fix our exposure issue, we can refactor our code by creating a .env file in our project’s base directory. This must be in the base file next to the docker-compose.yaml file for Docker to access the values. Then we define the key-value pairs or our secrets:

Figure 3. Our .env file with PostgreSQL database credentials.

Finally, we can reference these .env variables in our docker-compose with the following syntax:

Figure 4. Refactored docker-compose.yaml file with syntax for accessing environment variables.

We have separated the sensitive data from our code and can safely push the docker-compose.yaml file to our shared repo without worrying about exposing sensitive data, secrets, or API keys.

Note on Accessing Docker Container ENV Variables from the CLI

An important note to remember when using .env files with Docker is the separation pertains to code, not container instances. If we have access to the CLI in our local or cloud environment, we can still view the ENV variables and their values in a running container by running:

docker container inspect <container-name>

This command returns an output of all information for the selected container. A text search of “Env” in the terminal log will take you to an array of strings. Each string is a plain text key-value pair for all the container’s env variables.

Figure 5. Docker container inspect log readout for env variables in a running container.

--

--

Daniel Pericich

Former Big Beer Engineer turned Full Stack Software Engineer