The short answer
In Docker Compose, environment variables can be defined in the form of a list of key-value pairs in a file named .env located in the root directory of your project:
# .env
VERSION=v1.5
These variables can then be referenced in the compose.yaml file using the variable substitution syntax as follows:
# compose.yaml
version: '3'
services:
web:
image: "webapp:${VERSION}"
In this example, upon execution of the docker compose up command, Docker will substitute the VERSION variable with its value, resulting in the pulling of the webapp:v1.5 image. Note that, if the specified environment variable is not set, Docker will substitute the variable with an empty string.
Using custom .env files
Complex projects often include multiple environment files for different purposes, like development (e.g. .env.dev) and production (e.g. .env.prod).
In Compose, to use a specific environment file instead of the default .env file, you can use the docker compose up command with the —env-file flag as follows:
$ docker compose --env-file <file> up
Where:
- file is the absolute or relative path to the environment file.
For example:
$ docker-compose --env-file ./config/.env.dev up
Upon execution, the above command will bring up the services set in the compose.yaml file and substitute the values of the environment variables from the .env.dev file.
Understanding the order of precedence of environment variables
In Compose, the same environment variables can be defined in multiple places, like the shell environment, the default .env file, or an arbitrary environment file (e.g. .env.prod).
The order of precedence of these variables is as follows, from the highest to the lowest:
- 1. Shell environment: The variables set in your shell environment take the highest priority. Any variables set in the shell environment will always override those in your environment files.
- 2. Custom .env file: The environment variables loaded using the —env-file flag takes precedence over the default .env file located at the root of your project’s directory.
- 3. Default .env file: The variables set in the default .env file have the lowest precedence compared to the above sources.
Passing environment variables to services
In Compose, to pass environment variables defined in the .env file to the various services defined in the compose.yaml file, you can use the environment property as follows:
environment:
<name>: ${VARIABLE}
Where:
- name specifies the name of the environment variable for the container.
- VARIABLE specifies the name of the environment variable defined in the .env file.
For example:
# .env
PG_USERNAME="admin"
PG_PASSWORD="superadmin"
PG_DATABASE="shop"
# compose.yaml
version: '3'
services:
db:
image: postgres
environment:
POSTGRES_USER: ${PG_USERNAME}
POSTGRES_PASSWORD: ${PG_PASSWORD}
POSTGRES_DB: ${PG_DATABASE}
volumes:
- ./data:/var/lib/postgresql/data
ports:
- 5432:5432
Upon execution of the docker compose up command, Compose will start the web service and substitute the value of variables PG_USERNAME, PG_PASSWORD, and PG_DATABASE with the values defined in the .env file.
You can learn more about PostgreSQL with our article on how to launch a PostgreSQL instance using Docker Compose.
Easily retrieve this syntax using Warp AI feature
If you’re using Warp as your terminal, you can easily retrieve this syntax using the Warp AI feature:
Entering docker compose env file in the AI question input will prompt a human-readable step by step guide including code snippets.
Passing .env files to services
In Compose, to pass an entire environment file to a service listed in the compose.yaml file, you the env_file property as follows:
env_file:
- <file>
Where:
- file is the absolute or relative path to the environment file.
For example:
# compose.yaml
version: '3'
services:
web:
build: .
env_file:
- ./.env.dev
- ./.env.prod
Upon execution of the docker compose up command, Compose will start the web service and forward all the environment variables defined in the .env.dev and .env.prod files.
Note that since environment files are loaded sequentially, some variables may potentially be overwritten if already defined in preceding files.
Also note that environment variables defined under the environment have a higher precedence than the ones passed under the env_file property.
Defining default values for environment variables
In Compose, to assign a default fallback value to an unset or empty environment variable, you can use either one of the following variable substitution expressions:
${VAR:-default}
${VAR-default}
Where:
- ${VAR:-default} is used to indicate that the default value should be used when the variable VAR is empty or unset.
- ${VAR-default} is used to indicate that the default value should be used only when the variable VAR is not set.
For example:
# .env
NGINX_VERSION=1.19.5
CONTAINER_PORT=
# compose.yaml
version: '3'
services:
web:
image: "nginx:${NGINX_VERSION:-latest}"
environment:
- DATABASE_URL=${DB_URL:-mysql://user:password@dbhost/dbname}
ports:
- ${CONTAINER_PORT:-8080}
Upon execution of the docker-compose up command, the environment variables will be set as follows:
- NGINX_VERSION is set and non-empty in the .env file, so the specified value 1.19.5 will be used.
- DB_URL is not set in the .env file, so the default value mysql://user:password@dbhost/dbname will be used.
- CONTAINER_PORT is set but is empty in the .env file, so the default value 8080 will be used.
Enforcing required values for environment variables
In Compose, to enforce the existence or definition of a required environment variable, which is essential for the proper functioning of the application, you can use either one of the following variable substitution expressions:
${VAR:?error}
${VAR?error}
Where:
- ${VAR:?error} will exit with the specified error message error if the variable VAR is empty or unset.
- ${VAR?error} will exit with the specified error message error only if the variable VAR is not set.
For example:
# .env
TAG=v1.5
CONTAINER_PORT=
# compose.yaml
version: '3'
services:
web:
image: "nginx:${TAG:?Error: TAG is required}"
environment:
- API_KEY=${API_KEY:?Error: API_KEY is required}
ports:
- ${CONTAINER_PORT:?Error: Container Port is required}
- ${CONTAINER_PORT?Error: Container Port is required}
Upon execution of the docker-compose up command, the environment variables will be set as follows:
-
TAG is set and non-empty in the .env file, so the specified value v1.5 will be used.
-
API_KEY is not set in the .env file, so the command will exit with the error message Error: API_KEY is required.
-
CONTAINER_PORT is set but is empty in the .env file.
-
With the colon (:) syntax, the empty value for the CONTAINER_PORT will be used.
-
Without the colon (:) syntax, the command will not exit, and the empty value for the CONTAINER_PORT will be used.
Replacing environment variable values
In Compose, to allow your application to dynamically switch between different configurations based on the availability of specific values, you can overwrite the value of an existing or non-empty environment variable using either one of the following variable substitution expressions:
${VAR:+replacement}
${VAR+replacement}
Where:
- ${VAR:+replacement} replaces the value of the VAR variable with replacement if the variable is set and non-empty.
- ${VAR+replacement} replaces the value of the VAR variable with replacement only if the variable is set.
For example:
# .env
TAG=v1.5
CONTAINER_PORT=
# compose.yaml
version: '3'
services:
web:
image: "nginx:${TAG:+latest}"
environment:
DB_URL=${DB_URL:+mysql://user:password@dbhost/dbname}
ports:
- ${CONTAINER_PORT:+8080}
- ${CONTAINER_PORT+8080}
Upon execution of the docker-compose up command, the environment variables will be set as follows:
-
TAG is set and non-empty in the .env file, so the replacement value latest will be used.
-
DB_URL is not set in the .env file, so an empty value will be used for DB_URL.
-
CONTAINER_PORT is set but empty in the .env file.
-
With the colon (:) syntax, the empty value for the CONTAINER_PORT will be used.
-
Without the colon (:) syntax, the replacement value 8080 will be used.
Docker is a powerful tool that allows users to maintain a consistent development environment across various platforms. Docker environment variables are important configurations that impact all applications within a Docker container.
This tutorial explains everything you need to know about Docker environment variables. We list various ways to set environment variables in Docker, including how to set or override them using Docker CLI commands and Docker Compose, and some best practices to follow.
#What are Docker environment variables?
Docker environment variables are constant values that apply to all the applications running within a Docker container. These variables are used in many scenarios, such as to define the behavior of an application or script, configure parameters for docker images, and store important credentials like database credentials and API secrets.
What’s more, environment variables in Docker are critical to enhancing the container’s portability and flexibility. Environment variables let you adjust settings based on where you deploy the container without recreating the whole image and allow you to inject configurations at run time, enabling the container to work in various places and improve portability.
Ready to supercharge your Docker infrastructure? Scale effortlessly and enjoy flexible storage with Cherry Servers bare metal or virtual servers. Eliminate infrastructure headaches with free 24/7 technical support, pay-as-you-go pricing, and global availability.
#1. How to set environment variables in Dockerfile
A Dockerfile specifies everything it needs to build a Docker image. You can define two types of variables in the Dockerfile:
- Type 1:
ENV
— environment variables - Type 2:
ARG
— build time variables
The ENV contains environment variables that will be applied for any container built from it. You can specify the variables according to the following format.
ENV: env_variable_name=value
The following shows an example of a Dockerfile with environmental variables.
When you run a container from the image created with that Dockerfile, the applications or tasks within can use the Dockerfile environment variables.
#2. How to view environment variables in Docker
Docker provides a few options for inspecting and viewing the environmental variables currently set in the containers for debugging purposes.
#Option 1: Use docker inspect
command
You can use the docker inspect command to see what environmental variables have been set in your container or the docker image and check the Env
part of the JSON that generates. You need to specify the container or image ID.
docker inspect <containerId>/<Image_id>
To view only the environmental variables, use the following format of the inspect command.
docker inspect --format '{{.Confing.Env}}' <containerId>/<Image_id>
#Option 2: Use docker exec
command
Another way to see the configured environment variables is using Docker exec command. Use the docker exec
command following the format.
docker exec <containerID> env
#3. How to set and override Docker environment variables using docker run
command
Docker environment variables are defined in the Docker file or a separate environment file. When starting a container, you can set environmental variables using the command line using the docker run
command. You can also override the existing environment variables, specifying new values.
When using the docker run command, you can specify environmental variables in several ways.
#Option 1: Use the -e
option
You can use the -e
flag to set or override an environment variable when running a container. You can specify multiple variables by using multiple -e
flags.
docker run -e env_var=value <imageName>
Following is an example:
You can check if it is actually set by checking the images’ container id, as stated in the first section.
Also read: How to manage Linux environment variables
#Option 2: Use the --env-file
option
Another way to set or override environmental variables is using the —env-file option.
docker run --env-file <env_file_name> <imageName>
For example, we defined the following environmental variables in a dev.env
file.
API_KEY=WENMCOMnhfwDWER
MONGODB_URL=https://monogodbURL:uname:pw
In addition, you can also combine both -e
and --env-file
options to set and override environmental variables. If you set the same environment variable using both options, both the values will be set as Docker environment variables, and what you have defined using the -e
option will take precedence.
#4. How to set and override Docker environment variables using Docker Compose
Setting Docker environment variables at run time using the CLI is not a good practice for multi-container applications. Instead, we can use a special configuration file docker-compose.yaml
to define all environmental variables. This file contains all the configurations applicable to the container, and using one command, you can apply them when running the container.
#Option 1: Use the environment
attribute in the docker-compose.yaml file.
A typical docker-compose.yaml file will look like this. You can define the environmental variables in the environment
section.
services:
web:
build:
environment:
- key1="value1"
- key1="value1"
Let’s first clone the repository at https://github.com/wiztechth/compose-redis/tree/master, which will create a web application.
git clone https://github.com/wiztechth/compose-redis/tree/master
Next, define the following environmental variables in the docker-compose.yaml file.
environment:
- DEBUG=1
- ENV="staging"
Execute the following command by going into the application from the command line. It works exactly like the command docker run -e key=value
Next, using the following command, open up a new terminal window and check if the environmental variables you have defined have been applied using the docker compose run command.
docker compose run web env
Check how all the variables you have set have been applied. All other environmental variables come from the Dockerfile
.
#Option 2: Specify a separate environment variable file in docker-compose.yaml file
Alternatively, you can use a separate file to define your environmental variables and define that file in the env_file
section of the docker-compose.yaml file. For our example, let’s create a .env
file and specify the following environmental variables with values.
REDIS_PASSWORD=test
LOG_LEVEL=INFO
Then, include the path in the docker-compose.yaml file as follows.
services:
web:
build:
ports:
- "8000:5000"
env_file:
- .env
redis:
image: "redis:alpine"
In addition, you can use the following command to see the environmental variables configured to the application.
Also, you can combine multiple environmental variable files. To check this, rename the .env
file as stg.env and specify both the file paths as follows.
services:
web:
build:
ports:
- "8000:5000"
env_file:
- dev.env
- stg.env
redis:
image: "redis: alpine"
Specifying environmental variables in a separate file like this makes the containers flexible. For example, you can save the file in any location and give it a specific name, such as dev.env, prod.env, etc., according to the application’s environment. Therefore, you can have environment-specific configurations separately to organize your applications.
#Option 3: Set Docker environment variables with docker compose at the run time
In addition, docker compose
also allows setting environment variables in the command line using the --env-file
option.
docker compose --env-file <environmental_variables_file> up
To see how it works, add the following new sample environmental variable to the .env file you have created.
Then run the application and check the configured environmental variables.
#Option 4: Use docker compose run to set one-off environment variables
Another way to set environmental variables is when you use the ‘docker compose run’ command. The docker compose run
executes run one-off commands. This is exactly similar to the docker run
command. Similarly, you need to use the e
or --env-file
option with it.
The environment variables you set in this manner apply only to that particular container run. They will not be preserved for future containers you start from the same image unless you set them again.
For example, the following command will change the value of the variable DEBUG in our web application.
docker compose run -e DEBUG=0 web
#Best practices when setting Docker environment variables
When setting Docker environment variables, it is important to follow some best practices. Following are some important ones you could consider.
- Use a separate .env file to set Docker environment variables: it will help you to organize your variables across different environments. However, if you are deploying the docker repositories, ensure that you add it to the .gitignore file to prevent from committing them;
- Encrypt and store sensitive data: you should not define sensitive data like passwords and API keys directly in plain text. Use some form of encryption to store them and decrypt them within the application when using them;
- Avoid changing environment variables within a running container: to ensure consistency between different environments, never change them at run time. Instead, change after the container is stopped and start a new instance;
- Use a standard naming convention: to ensure consistency, use a standard naming convention;
- Maintain the environmental variables regularly: review the defined environment variables regularly to ensure there are no outdated values.
#Wrapping up
In this guide, we discussed the significance of Docker environment variables in ensuring consistent behavior for applications across various platforms. We’ve highlighted the role of the Dockerfile environment variables and explored how Docker offers flexibility in adjusting them through CLI commands and Docker Compose. Moreover, by adopting the best practices we highlighted, you can securely manage sensitive data, achieve consistent configurations, and enhance container deployment efficiency.
Run your Docker containers at scale with Cherry Servers open cloud infrastructure. Choose a dedicated bare metal or virtual server with flexible storage, pricing, global availability, and free 24/7 technical support to focus on your container development workflow.
Docker environment variables play an essential role in configuring and managing applications that are containerized. This gives developers the perfect opportunity to define dynamic values that can be used within the Docker containers without actually modifying the application code.
Docker environment variables help with:
- Configuration Management: Switch between different configurations (e.g., development, staging, and production).
- Security: Avoid hardcoding sensitive information like API keys and passwords in Dockerfiles.
- Portability: Ensure consistent behavior across different environments and deployment setups.
Docker provides multiple ways to define and use environment variables, such as:
- Docker Compose Environment Variables (docker-compose.yml) – Define variables in an environment section or an external .env file.
- Dockerfile (ENV instruction) – Set default environment variables at the image level.
- docker run command – Pass environment variables dynamically when running a container.
In this guide, we will walk through all these methods and learn the best ways to manage variables effectively in a Docker file.
Types of Docker Environment Variables
Docker provides two primary types of environment variables:
- ENV (Environment Variables in Running Containers)
A Dockerfile uses ENV command to define Docker environment variables that persist in a running container. These can be accessed within the container by applications.
Tech Delivered to Your Inbox!
Get exclusive access to all things tech-savvy, and be the first to receive
the latest updates directly in your inbox.
Example:
FROM ubuntu:latest
ENV APP_ENV=production
CMD echo “Running in $APP_ENV mode”
- These variables are set at build time but can be overridden at runtime using the -e flag with docker run.
- They are useful for defining configurations like database URLs and API keys.
- ARG (Build-Time Variables)
The ARG command in Dockerfile defines variables that are only accessible during the image build process. These variables cannot be accessed after the container starts.
Example:
FROM ubuntu:latest
ARG VERSION=1.0
RUN echo “Building version $VERSION”
- ARG variables are useful for passing build-specific values such as software versions or package names.
- They can be set using the –build-arg flag with docker build.
Key Differences Between ENV and ARG:
Enhance Your CyerPanel Experience Today!
Discover a world of enhanced features and show your support for our ongoing development with CyberPanel add-ons. Elevate your experience today!
Feature | ENV | ARG |
Available at Build Time | ✅ | ✅ |
Available at Runtime | ✅ | ❌ |
Can Be Overridden at Runtime | ✅ | ❌ |
Persist in the Container | ✅ | ❌ |
Why Use Docker Compose Environment Variables?
Docker compose environment variables provide an easy way to configure applications without modifying source code. Here’s why they are useful:
- Easier Configuration Management
In place of hardcoding values in the docker-compose.yml file, you can use variables to make deployments more dynamic.
- Improved Security
Sensitive & secret information like database passwords and API keys can be stored in an .env file instead of being exposed in the configuration file.
- Portability Across Environments
Docker-compose environment variables help adapt the same Docker setup for different environments (e.g. development, staging, and production) without modifying the docker-compose.yml file.
- Simplifies Updates and Maintenance
Updating configurations is easy since changes can be made in the .env file without modifying the application file.
Example: Using Environment Variables in Docker Compose
version: ‘3’
services:
app:
image: my-app
environment:
– DATABASE_URL=${DATABASE_URL}
By using an .env file:
DATABASE_URL=mysql://user:password@db:3306/mydatabase
This setup ensures that the database URL is not exposed in the docker-compose.yml file, making deployments more secure and manageable.
Setting Up Environment Variables in Docker Compose
Docker compose provides multiple ways to set up variables, making it super simple to manage dynamic configurations. Here are the three methods:
- Using the environment Section
The environment section in a docker-compose.yml file allows you to define environment variables directly within the service.
Example:
version: ‘3’
services:
app:
image: my-app
environment:
– APP_ENV=production
– DATABASE_URL=mysql://user:password@db:3306/mydatabase
- Using an .env File
A more secure and flexible approach is to use an .env file to store environment variables separately. Docker Compose automatically loads the variables from this file.
Example:
.env file
APP_ENV=production
DATABASE_URL=mysql://user:password@db:3306/mydatabase
docker-compose.yml file
version: ‘3’
services:
app:
image: my-app
env_file:
– .env
- Passing Variables from the Host System
Docker Compose allows you to pass environment variables from the host machine to the container dynamically.
Example:
Run the following command in the terminal before running docker-compose up:
export APP_ENV=production
export DATABASE_URL=mysql://user:password@db:3306/mydatabase
docker-compose up
Alternatively, use placeholders in docker-compose.yml:
version: ‘3’
services:
app:
image: my-app
environment:
– APP_ENV=${APP_ENV}
– DATABASE_URL=${DATABASE_URL}
How to View Docker Environment Variables
To check the Docker environment variables inside a running container, you can use multiple methods, such as:
- Using the env Command
Run the following command to view all environment variables inside a running container:
docker exec -it <container_id> env
Example:
docker exec -it my-container env
- Using the printenv Command
Another way to list environment variables inside a container is:
docker exec -it <container_id> printenv
- Inspecting a Container’s Environment Variables
To check environment variables without accessing the container, use:
docker inspect <container_id>
This returns a JSON output. To filter only environment variables:
docker inspect –format='{{range .Config.Env}}{{println .}}{{end}}’ <container_id>
Using Environment Variables with docker run
When you are running a Docker container, you can pass Docker environment variables dynamically with the -e flag.
- Passing a Single Variable
docker run -e APP_ENV=production my-app
Inside the container, APP_ENV will be available for production.
- Passing Multiple Variables
docker run -e APP_ENV=production -e DB_USER=root -e DB_PASS=secret my-app
- Using an .env File
Instead of passing all the variables manually, you can use an .env file.
Example .env file:
APP_ENV=production
DB_USER=root
DB_PASS=secret
Run the container with:
docker run –env-file .env my-app
Best Practices for Managing Docker Environment Variables
Managing Docker compose environment variables effectively ensures reliable security, maintainability, and flexibility. Here are some of the best practices to follow:
Best Practice | Description | Example/Implementation |
Use an .env File for Configuration | Store environment variables separately to keep docker-compose.yml clean. | Define variables in an .env file and reference it in docker-compose.yml. |
Avoid Storing Sensitive Data in Dockerfiles | Prevent hard coded credentials in Docker images. | Use ENV for non-sensitive values and external secrets management tools for sensitive data. |
Use docker run –env-file for Secure Deployment | Prevents exposure of credentials in terminal history. | docker run –env-file .env my-app |
Use the Least Privilege Principle | Define only necessary environment variables to reduce security risks. | Avoid exposing system-wide variables unless required. |
Keep Environment Variables Consistent Across Environments | Use separate .env files for different environments. | .env.dev for development, .env.prod for production. |
Use Docker Secrets for Sensitive Data | For production, store passwords and API keys securely. | docker secret create my_secret secret.txt |
Conclusion
Docker compose environment variables provide a powerful means to configure applications dynamically. By implementing these strategies, you can efficiently manage environment variables within the containers. This ensures a more robust Docker-based application deployment.
1. What are environment variables in Docker Compose?
Environment variables in Docker Compose allow you to configure services dynamically without hardcoding values in the docker-compose.yml
file.
2. Can I set environment variables inline when running docker-compose up
?
Yes, you can pass variables inline:DB_PASSWORD=secret docker-compose up -d
3. How do I override environment variables in Docker Compose?
Define a variable in multiple places; Docker Compose follows this priority order:
1. Inline (VAR=value docker-compose up
)
2. Exported system variables (export VAR=value
)
3. .env
file
4. docker-compose.yml
Docker Compose is a powerful tool for orchestrating multi-container applications. It allows software engineers to define and manage environment variables seamlessly. In the realm of modern software development and containerization, environment variables play a pivotal role in configuring applications and services. They offer a flexible way to manage settings, credentials, and other secret and dynamic values without hardcoding them into code. In this comprehensive guide, you will delve into the intricacies of setting up environment variables in Docker Compose, covering everything from the basics to best practices. Let’s get going!
Table of contents #
- Prerequisites
- Using MySQL container as an example
- How to define environment variables in Docker run
- Adding environment variables in the Docker compose file
- Substitute from shell or .env file
- Pass the env file with —env-file argument
- Putting environment variable in an external file
- Use the env_file attribute
- Docker compose environment variables precedence
- Best practices for Docker compose environment variables
- Conclusion
Prerequisites #
Before you go to the code section, the following are some prerequisites:
- You have docker and docker-compose installed on your local machine. This post will make use of Docker 24.0.2 and docker-compose v 2.18.1 on a Mac. Docker compose can be run with
docker-compose
ordocker compose
command in this version of docker and docker-compose. - Prior experience with docker and docker-compose will be helpful.
- Knowledge of MySQL and injecting environment variables will be useful but not necessary.
For the context of this guide, you will use docker-compose in a development setting only. You are not expected to use docker-compose to orchestrate or scale containers. Scaling and orchestrating containers is done in a better way by Kubernetes. Given the requisites are mentioned, in the next section you will learn about MySQL container as an example for the whole post.
Using MySQL container as an example #
For this post, you will use a MySQL 8.1 container as an example. You will first run the container without docker-compose and inject some environment variables. Then you will learn how to run the same MySQL container with docker compose and two main ways to inject those same environment variables.
How to define environment variables in Docker run #
You can easily run a MySQL 8.1 container pulling the Docker image from DockerHub with the Docker run command. First run mkdir /tmp/mysql-data
to create a folder to hold the MySQL data then run the docker run
command as follows:
docker run --name mysql81 --rm -v /tmp/mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=mauFJcuf5dhRMQrjj -e MYSQL_DATABASE=testing -p 3306:3306 -it mysql:8.1
The parameters in the above docker run command are doing the following things:
- the option
--name
is used to assign the container the name «mysql8». If this option is not provided, Docker will assign a random name to the container - To ensure the container is removed when it stops, the —rm flag is utilized
- A volume -v is attached to /tmp/mysql-data and /var/lib/mysql, ensuring that the data is retained between container restarts. However, this data will be removed when the host machine restarts, given its location in /tmp.
- Environment variables -e are set to configure the MySQL instance. For instance,
MYSQL_ROOT_PASSWORD
is set to «mauFJcuf5dhRMQrjj» for the root user’s password, andMYSQL_DATABASE
is set to «testing» to initialize a database named «testing». This is the main focus here. - The option
-p 3306:3306
maps the host port 3306 to the container’s port 3306. Port 3306 is MySQL’s default port, and you can choose to map to a different host port, such as 3307:3306, which would link the local port 3307 to the container’s port 3306. - The combination of -it ensures that the container runs interactively, allowing the display of all logs as a terminal is allocated. We’re using the official MySQL image version 8.1.
When it runs successfully it will show an output like the below:
If you want you can go into the container using the docker exec command.
Adding environment variables in the Docker compose file #
You can run the same MySQL container much more easily, without the need to remember all the parameters more declaratively with a docker-compose.yml
file which looks like the below:
version: '3.8'
services:
db:
image: mysql:8.1
cap_add:
- SYS_NICE
restart: always
environment:
- MYSQL_DATABASE=quotes
- MYSQL_ROOT_PASSWORD=mauFJcuf5dhRMQrjj
ports:
- '3306:3306'
volumes:
- db:/var/lib/mysql
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
volumes:
db:
driver: local
Here the environment variables are passed using the environment
attribute. An init file is used to load the database with a sample quotes schema and some data, you can see the file and its content in this GitHub repository. You can learn more about Docker-compose and MySQL by reading this tutorial. For now, let’s focus on the environment variable part.
As you can see above, the environment variables are part of the docker-compose file, and the sensitive variables are not replaced by another file or OS/shell variables. You will learn substitution in the next section.
Substitute from shell or .env file #
To make the environment variables more obscure and not easily visible in the docker-compose.yml file you can substitute them. It can be substituted either from a .env
file or from a shell variable. You can add a file named .env
on the same level as your docker-compose.yml
file with the following contents:
MYSQL_DATABASE=quotes
MYSQL_ROOT_PASSWORD=mauFJcuf5dhRMQrjj
Then you can change your docker-compose file to look like the below:
version: '3.8'
services:
db:
image: mysql:8.1
cap_add:
- SYS_NICE
restart: always
environment:
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
ports:
- '3306:3306'
volumes:
- db:/var/lib/mysql
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
volumes:
db:
driver: local
Now the variables ${MYSQL_DATABASE}
and ${MYSQL_ROOT_PASSWORD}
will be replaced by the values store in the .env
file. You can check the final docker-compose.yml
file that will be used for docker-compose commands by running docker compose -f docker-compose-02-env-file.yml config
it will show you the compiled file as below:
You can also set the variable as Shell variables and it will also be used. For example you can set the MYSQL_DATABASE
variable to test
by executing export MYSQL_DATABASE=test
. After that if you run docker compose -f docker-compose-02-env-file.yml config
you will see:
In addition to the environment variables, you can also replace other things in the docker-compose.yml
file with this pattern. For instance, if you want to put image: mysql:{MYSQL_VERSION}
and get it replaced with a value from .env
or shell variable it can be done too.
Pass the env file with —env-file argument #
If you need to use a different set of environment variables for different environments on the fly then you can do it using --env-file
argument with docker-compose commands. This will substitute the variable on the docker-compose.yml
file for each command. Below is a .env.test
file with the following variables:
MYSQL_DATABASE=quotes_test
MYSQL_ROOT_PASSWORD=test
To use this file while testing, you can use the command shown next:
docker compose --env-file .env.test -f docker-compose-02-env-file.yml config
It will use the .env.test
file for the environment variables and the used docker-compose.yml
file will look like the below:
If you don’t want to list your environment variables in the docker-compose.yml
file with the `environment1 attribute, that is possible. For that, you will need to use an external file, which will be elaborated in the next section.
Putting environment variable in an external file #
You can put all your environment variables in an external file like a .env
file. You can use the same .env
file from the above example that has the MYSQL_DATABASE
and MYSQL_ROOT_PASSWORD
variables. To use this file to feed in the environment variable for the running docker container you will use the env_file
attribute. It is discussed in the next section.
Use the env_file attribute #
If you want you can also pass multiple files using the env_file
attribute in docker-compose. To run the MySQL container with the env_file
attribute, it will be changed to look as follows:
version: '3.8'
services:
db:
image: mysql:8.1
cap_add:
- SYS_NICE
restart: always
env_file:
- .env
ports:
- '3306:3306'
volumes:
- db:/var/lib/mysql
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
volumes:
db:
driver: local
The file has been saved as docker-compose-03-env-file-attr.yml
and you can check the final docker compose file with docker compose -f docker-compose-03-env-file-attr.yml config
. It will look similar to the above file with the environment
variable. But this one is taking the environment variables from an external file with the env_file
attribute.
Docker compose environment variables precedence #
There are multiple ways to pass the environment variables in docker compose. So an order is needed to decide what method takes precedence over the other. The priority is as follows:
- Configured via docker compose run -e in the command-line interface (CLI).
- Substituted from your shell environment variables.
- Defined through the environment attribute in the Compose file.
- Utilization of the —env-file argument in the CLI.
- Leverage of the env_file attribute in the Compose file.
- Establishment within an .env file positioned at the root of your project directory.
- Set within a container image utilizing the ENV directive. Worth noting is that any ARG or ENV settings within a Dockerfile come into play only if no Docker Compose entries for environment, env_file, or run —env are present.
So now you know that if you set a bash variable it will override setting the same environment variable on a file passed with --env-file
. So be careful about the precedence of the variables to get your desired output.
All the examples of this post are in this GitHub repository for your reference. Some best practices regarding docker-compose environment variables are discussed next.
Best practices for Docker compose environment variables #
Below are some best practices for using environment variables in a docker-compose file:
- Use environment variables to store sensitive data, such as passwords and API keys. This will help to keep your data secure and prevent it from being exposed. * Substitute them from the shell/OS environment variable on a docker-compose file.
- Use a consistent naming convention for environment variables. This will make it easier to track and manage your environment variables.
- Use a version control system to track changes to environment variables. This will help you to keep track of changes to your environment variables and identify any potential security vulnerabilities.
- Use a secrets management tool to store sensitive data. This will help to keep your data secure and prevent it from being exposed.
Those are some practices you should remember for docker-compose environment variables and environment variables in general.
Conclusion #
In this guide, you learned how to put environment variables with a regular docker run command. Then you were guided to use environment variables with the environment
attribute in a docker-compose file for a MySQL container. After that, you used some environment variable substitution from shell and .env
files.
You also learned to use the env_file
attribute of the docker-compose file to put the environment variables in an external file. Toward the end, you found out about the precedence of environment variables in docker-compose and finally learned some best practices for them.
I hope now you are more confident about using environment variables properly in the docker-compose context. Happy dockerizing your apps!
When working with Docker Compose, using environment variables is one of the best ways to make your configuration dynamic, reusable, and secure.
In this blog, you’ll learn:
- 💡 What are environment variables?
- 🧩 How to use them in Docker Compose
- 📁 The role of
.env
files - 🧪 Real-world examples
- ✅ Best practices to keep things clean and secure
Let’s get started!
💡 What Are Environment Variables?
Environment variables are key-value pairs used to store configuration settings. They let you define data like:
- Database names and passwords
- API keys
- Port numbers
- Paths
- Environment types (e.g., development, production)
This helps you avoid hardcoding sensitive or changing values directly into your code or Docker Compose file.
⚙️ Using Environment Variables in docker-compose.yml
Docker Compose allows you to use environment variables by referencing them with ${}
syntax.
✅ Example
version: '3.9'
services:
web:
image: "nginx:${NGINX_VERSION}"
ports:
- "${APP_PORT}:80"
environment:
- APP_ENV=${APP_ENV}
- API_KEY=${API_KEY}
Here:
NGINX_VERSION
,APP_PORT
,APP_ENV
, andAPI_KEY
are environment variables.- Docker Compose will look for these in your system environment or a
.env
file.
📁 Using a .env
File
Docker Compose automatically looks for a file named .env
in the same directory as your docker-compose.yml
.
✅ .env
Example
NGINX_VERSION=latest
APP_PORT=8080
APP_ENV=development
API_KEY=12345-abcdef
🔁 Now you can run:
docker-compose up
Docker Compose will automatically inject the values from .env
.
🧪 Real-World Example
docker-compose.yml
version: '3.9'
services:
app:
build:
context: .
args:
NODE_ENV: ${NODE_ENV}
environment:
- NODE_ENV=${NODE_ENV}
ports:
- "${APP_PORT}:3000"
volumes:
- .:/app
.env
NODE_ENV=development
APP_PORT=3000
📤 Injecting Environment Variables via CLI
You can also pass environment variables inline when running Docker Compose:
NODE_ENV=production APP_PORT=8080 docker-compose up
These will override what’s in your .env
file or system.
🧪 Using env_file
in Compose
If you want to load variables into a service’s container, use the env_file
property.
Example
services:
app:
image: myapp
env_file:
- ./app.env
app.env
DB_HOST=db
DB_USER=root
DB_PASS=password
📝 This file is loaded into the container’s environment, not the Compose file itself.
🧠 Key Differences
Feature | .env file |
env_file |
---|---|---|
Used by | Docker Compose engine | Container at runtime |
Purpose | Replaces variables in docker-compose.yml |
Sets environment inside container |
Syntax | KEY=value |
KEY=value |
Scope | File-wide | Service-specific |
✅ Best Practices
🔒 Keep .env
files out of version control
Use .gitignore
to avoid committing secrets:
.env
*.env
🧹 Use defaults in your Compose file
ports:
- "${APP_PORT:-8000}:80"
🛠️ Use docker-compose config
to debug
Run this to see the final file after variable substitution:
docker-compose config
🧠 Summary
Feature | Description |
---|---|
${VAR} |
Use environment variables inside Compose |
.env |
File loaded automatically by Compose |
env_file |
Loads variables into container runtime |
CLI variables | Override variables temporarily |
docker-compose config |
Show merged config with variables expanded |
🚀 Final Thoughts
Using environment variables in Docker Compose is a simple but powerful way to:
- Make your setup environment-independent
- Keep secrets out of your Compose file
- Customize behavior for dev, staging, or prod
- Follow 12-Factor App principles
Try replacing some of your hardcoded values with ${}
variables today — your future self will thank you! 🙌