Environment variables play a crucial role in Docker Compose for managing configuration and sensitive data across containerized applications. They provide a flexible way to inject values such as database credentials, API keys, and service ports into containerized environments without hardcoding them into the source code or Docker images.
In Docker Compose, you can define environment variables in multiple ways, such as directly in the compose.yml file (note: the modern naming convention is compose.yml rather than docker-compose.yml), through .env files, or by passing them during runtime. This flexibility allows for easy configuration management across different deployment environments.
Prerequisites
Before starting, ensure the following:
- Docker and Docker Compose are installed on your system. If not, follow the official Docker installation guide and Docker Compose installation instructions.
- A basic understanding of Docker Compose syntax and YAML configuration files.
- A sample application to test environment variable configurations. You can create a simple Python or Node.js app.
Step 1: Create a Simple Docker Compose File
To begin, let's create a compose.yml file for a basic web application. This will serve as the foundation for our environment variable configurations.
-
Create a directory for the project:
mkdir docker-compose-env-demo cd docker-compose-env-demo -
Create a
compose.ymlfile:nano compose.ymlNote: The modern naming convention is
compose.ymlrather thandocker-compose.ymlDocker Compose Environment Variables. -
Add the following example configuration:
services: web: image: nginx:latest ports: - "127.0.0.1:${WEB_PORT:-80}:80" environment: - APP_ENV=${APP_ENV:-production}
This configuration sets up an Nginx service and uses environment variables for the WEB_PORT and APP_ENV.
Step 2: Define Environment Variables in a .env File
A .env file provides a centralized and secure way to define environment variables for Docker Compose.
-
In the same directory as
docker-compose.yml, create a.envfile:nano .env -
Add the following variables:
WEB_PORT=8080 APP_ENV=production -
Save and close the file. Docker Compose automatically loads this file to inject the variables into the services defined in
docker-compose.yml. -
Test the configuration by running:
docker-compose upYou should see the Nginx service running on port 8080.
Step 3: Set Environment Variables Directly in the Compose File
You can define environment variables directly in the compose.yml file. This approach is useful for default values or when you want to make the configuration explicit within the file.
-
Modify the
compose.ymlfile:services: web: image: nginx:latest ports: - "127.0.0.1:8080:80" environment: - APP_ENV=production - DEBUG=false -
Run the configuration:
docker compose upNginx should run on localhost port 8080 with the
APP_ENVvariable set toproductionandDEBUGset tofalse. -
To verify the environment variables, you can use:
docker compose configThis will show you the resolved configuration, including the set environment variables.
Step 4: Override Variables with Shell Values
Docker Compose allows you to override .env file values with shell environment variables. This is useful for temporary changes or when deploying to different environments.
-
Set a shell variable:
export WEB_PORT=9090 -
Run Docker Compose:
docker compose up -
Verify that the container is now binding to port 9090 instead of 8080:
docker compose psThis demonstrates that shell variables take precedence over
.envvalues Docker Compose Environment Variables Precedence. -
To see the resolved configuration, including the overridden values:
docker compose config
Note: Remember to unset the shell variable when you're done to avoid unexpected behavior in future runs:
unset WEB_PORT
Step 5: Secure Sensitive Variables with Docker Secrets
For sensitive data, it's best to avoid using .env files or plain-text variables in the Compose file. Instead, use Docker Secrets for enhanced security.
-
Create a file for the secret:
echo "supersecretkey" > secret_key.txt -
Update
compose.ymlto use the secret:services: web: image: nginx:latest ports: - "127.0.0.1:${WEB_PORT:-80}:80" secrets: - app_secret environment: - APP_SECRET_FILE=/run/secrets/app_secret secrets: app_secret: file: ./secret_key.txt -
Deploy the stack:
docker compose upThe secret is now securely available inside the container at
/run/secrets/app_secret.
Step 6: Verify Environment Variables in Containers
You can inspect environment variables within a running container for debugging.
-
Find the container's name:
docker ps -
Use
docker execto access the container and list environment variables:docker exec -it <container_name> env -
Verify that the
APP_ENVand other variables are correctly set.
Step 6: Verify Environment Variables in Containers
-
Start your Docker Compose project if it's not already running:
docker compose up -d -
List the running containers:
docker compose psThis command will show you all the containers defined in your Compose file and their current status.
-
Use
docker compose execto access the container and list environment variables:docker compose exec web envThis command runs the
envcommand inside thewebservice container, listing all environment variables Docker Compose Run. -
To verify specific variables, you can use grep:
docker compose exec web env | grep APP_ENV -
For more detailed inspection, you can start a shell inside the container:
docker compose exec web shOnce inside the container, you can run commands to inspect the environment or your application's configuration.
-
To check if your application is correctly using the environment variables, you might need to inspect application logs:
docker compose logs web
Step 7: Debug Common Issues
When working with environment variables in Docker Compose, you might encounter some common issues.
-
Variable Not Substituting:
- Ensure variables are correctly referenced in
compose.ymlusing${VARIABLE_NAME}syntax. - Use the
docker compose configcommand to check if variables are being interpolated correctly.
- Ensure variables are correctly referenced in
-
Shell Variables Not Loading:
- Confirm that
export VARIABLE=valueis used and the terminal session has the variables. - Remember that shell variables are only available in the current session. For persistence, add them to your shell's configuration file (e.g.,
.bashrcor.zshrc).
- Confirm that
-
.envFile Not Loaded:- Verify that the
.envfile is in the same directory as thecompose.yml. - Check file permissions to ensure Docker can read the
.envfile. - Use the
--env-fileoption to specify a different.envfile location:docker compose --env-file ./config/.env.dev up.
- Verify that the
-
Variable Precedence Issues:
- Understand the order of precedence: Compose file > Shell environment >
.envfile . - Use
docker compose configto see the final resolved configuration.
- Understand the order of precedence: Compose file > Shell environment >
-
Sensitive Data Exposure:
- Avoid putting sensitive data directly in
compose.ymlor.envfiles. - Use Docker secrets for sensitive information, especially in production environments.
- Avoid putting sensitive data directly in
-
Unexpected Default Values:
- When using variable substitution with default values (e.g.,
${VARIABLE:-default}), ensure the default value is appropriate for your use case. - Be aware that an empty string is considered a set value, so
${VARIABLE:-default}will use the empty string ifVARIABLEis set to an empty string.
- When using variable substitution with default values (e.g.,
Conclusion
This tutorial demonstrated how to set and use environment variables in Docker Compose using .env files, direct definitions, runtime overrides, and secrets for sensitive data. Proper management of environment variables enhances the security and maintainability of containerized applications, enabling better configuration practices.
For advanced scenarios, refer to the Docker Compose documentation for more details.