When you manage complex Docker deployments, hard-coding environment variables directly inside docker-compose.yml quickly becomes a maintenance problem. The solution is to declare those variables in a dedicated .env file that Docker Compose reads automatically. This guide explains what the file is, how to populate it, and how to reference its values in your Compose configuration.
What You’ll Need
- A working installation of Docker
- Docker Compose (either the standalone
docker-composebinary or thedocker composeplugin bundled with Docker Engine) - A project directory that already contains, or will contain, a
docker-compose.ymlfile
What Is the .env File?
The .env file is a plain-text file that Docker Compose reads before processing docker-compose.yml. Each line defines one variable using the simple KEY=VALUE syntax. Docker Compose substitutes those values wherever you reference ${KEY} inside your Compose file. The file must be named exactly .env (including the leading dot) and placed in the same directory as your docker-compose.yml.
Declaring Variables in the .env File
Each variable is declared on its own line in the following format:
VARIABLE_NAME=VALUE
Lines beginning with # are treated as comments and ignored. Blank lines are also ignored. There is no need to quote values unless they contain whitespace that you want to preserve.
A practical example for a MySQL-backed application might look like this:
# Database configuration
DB_NAME=dbase
DB_USER=dbuser
DB_PW=dbpassword
DB_ROOT_PW=dbrootpwCode language: PHP (php)
Save this file as .env in the same directory as your docker-compose.yml.
Referencing .env Variables in docker-compose.yml
Inside docker-compose.yml, reference a variable by wrapping its name in ${}. Docker Compose performs the substitution automatically when you run any docker compose command.
services:
db:
image: mysql
environment:
MYSQL_DATABASE: "${DB_NAME}"
MYSQL_USER: "${DB_USER}"
MYSQL_ROOT_PASSWORD: "${DB_ROOT_PW}"
MYSQL_PASSWORD: "${DB_PW}"Code language: JavaScript (javascript)
When you run docker compose up, Docker Compose checks for a .env file in the project directory first, loads every variable it finds, and then resolves all ${} placeholders in the Compose file before starting any containers.
Comparing .env with Hard-Coded Values
Without a .env file, you would write environment variables directly into docker-compose.yml:
services:
db:
image: mysql
environment:
MYSQL_DATABASE: "dbase"
MYSQL_USER: "dbuser"
MYSQL_ROOT_PASSWORD: "dbrootpw"
MYSQL_PASSWORD: "dbpassword"Code language: JavaScript (javascript)
This approach has several drawbacks:
- Credentials in source control. If you commit
docker-compose.ymlto a repository, sensitive values like passwords are exposed. - Difficult to reuse. Every new project or environment (development, staging, production) requires you to edit the Compose file directly.
- Error-prone updates. The same value may appear in multiple places, making updates inconsistent.
Using a .env file addresses all three issues. You can add .env to your .gitignore so secrets are never committed, share a single Compose file across environments by swapping only the .env file, and update a value in one place rather than hunting through YAML.
Keeping Secrets Out of Version Control
Add .env to your .gitignore file to prevent it from being committed:
# .gitignore
.envCode language: CSS (css)
It is good practice to commit a .env.example file instead. This file contains all the required variable names with placeholder or safe default values, giving other developers a template to copy and fill in.
# .env.example
DB_NAME=your_database_name
DB_USER=your_db_user
DB_PW=your_db_password
DB_ROOT_PW=your_db_root_passwordCode language: PHP (php)
Using Multiple Environment Files
If you need to load variables from a file with a different name or path, Docker Compose supports the --env-file flag:
docker compose --env-file ./config/production.env up
This is useful for maintaining separate configurations for different deployment environments without changing the default .env file.
Summary
The .env file is a small but powerful tool in the Docker Compose workflow. By moving environment variables out of docker-compose.yml and into a dedicated file, you gain cleaner YAML, safer secret management, and configurations that are easier to reuse across environments. Place the file next to your Compose file, declare your variables in KEY=VALUE format, reference them with ${KEY} in your Compose YAML, and add .env to .gitignore.