← Back to Blog DevOps

Docker Compose env_file vs environment: When to Use Which

Need a quick solution?

Validate your YAML, clean up environment files, or convert run commands 100% locally in your browser:

Configuring environment variables correctly in Docker Compose is critical for building secure, scalable, and portable applications. When orchestrating services, you frequently need to decide how to supply your configurations—whether to define them directly in your docker-compose.yml file or split them into isolated environment files.

Docker Compose provides two primary mechanisms to achieve this: the environment key and the env_file key. While both populate variables in your containers, they serve entirely different deployment strategies.

1. The Quick Definition

  • environment: Used to declare individual environment variables directly **inline** within the Compose configuration file. It is ideal for non-sensitive configurations that vary between development states, like ports or debug flags.
  • env_file: Used to load a **separate text file** containing key-value environment pairs (like .env) on startup. This is excellent for keeping sensitive credentials separate from your main YAML markup.

2. Priority Rules (How Overrides Work)

One of the biggest causes of configuration bugs is variable duplication. If the same environment variable (e.g., API_URL) is defined in multiple places, Docker Compose resolves the values using a strict order of priority:

  1. Command-line values: Variables defined directly in your host shell where you run docker compose up override everything.
  2. environment key: The inline variables defined in your docker-compose.yml override any file imports.
  3. env_file key: Variables imported from files referenced inside your compose configuration.
  4. Default .env file: The standard, fallback .env file in the directory where your command is executed.

Rule of thumb: The more explicit/runtime-specific the definition is, the higher its evaluation priority.

3. Code Examples

Let's look at a typical production Nginx or Node.js environment configuration file (e.g., ./config/.env):

DATABASE_URL=postgresql://db_user:password@db_host:5432/production
API_KEY=super_secret_token_abc123

Now, here is how we import that file while overriding static runtime parameters inside our main docker-compose.yml configuration:

version: "3.8"
services:
  web:
    image: node:18
    ports:
      - "3000:3000"
    
    # 1. Using environment (Inline definition)
    environment:
      - NODE_ENV=production
      - PORT=3000
      - DB_CONNECTION_TIMEOUT=30
      
    # 2. Using env_file (Loads external key-value text files)
    env_file:
      - ./config/.env

Summary Comparison Table

Feature environment env_file
Definition Location Inline inside docker-compose.yml Separate external text file (e.g., .env)
Secret Safety Low (sensitive variables should not be committed to Git) High (the referenced file can be added to .gitignore)
Override Strength High (always overrides env_file variables) Medium (can be overridden by explicit inline variables)
Syntax Format YAML array or dictionary Text file with KEY=VALUE entries

Frequently Asked Questions

What is the difference between env_file and environment in Docker Compose?
The environment key defines individual environment variables inline in the docker-compose.yml file. The env_file key points to a separate text file (like .env) containing key-value pairs that are imported as environment variables.
Which has higher priority: environment or env_file?
Variables defined under the environment key always override variables defined in files specified under the env_file key. The order of evaluation is: environment variables > env_file variables > default .env file variables.
How do I secure secrets in Docker Compose?
Never commit your secret .env files to version control. Add .env to your .gitignore, define placeholder variables in docker-compose.yml, and load the real values at runtime from your system environment or a private env file.