Using env files in docker-compose.yml

When working with Docker, managing environment variables efficiently is crucial, especially when running docker-compose in different environments. Instead of hardcoding values or maintaining multiple docker-compose.yml files, you can leverage .env files to store and pass environment variables dynamically.

Why Use env Files with docker-compose?

Using an .env file allows you to:

  • Keep sensitive information (e.g., database credentials) out of version-controlled YAML files.
  • Maintain a single docker-compose.yml while supporting multiple environments.
  • Improve readability and ease of configuration management.

Basic Usage of env Files in docker-compose

1. Create an .env File

First, create a .env file with the required environment variables:

POSTGRES_USER='postgres'
POSTGRES_PASSWORD='postgres'
POSTGRES_DB='lireddit'

2. Reference the .env File in docker-compose.yml

Modify your docker-compose.yml to reference this file:

version: "3.6"
services:
  web:
    build: ./server/
    volumes:
      - server:/app
      - server_node_modules:/app/node_modules
    ports:
      - "4000:4000"
    depends_on:
      - postgres
    environment:
      - NODE_ENV=development
  postgres:
    image: postgres:13.2
    restart: always
    ports:
      - "5432:5432"
    volumes:
      - db_data:/var/lib/postgresql/data
    env_file:
      - .env

volumes:
  db_data:
  server:
    driver_opts:
      type: none
      device: ${PWD}/server
      o: bind
  server_node_modules:
    driver_opts:
      type: none
      device: ${PWD}/server/node_modules
      o: bind

3. How It Works

The env_file field in the postgres service instructs Docker to load environment variables from the .env file. This is equivalent to defining them manually as shown in the web service.

Using env Files for Multiple Services

You can also use a single .env file for multiple services:

POSTGRES_USER='postgres'
POSTGRES_PASSWORD='postgres'
POSTGRES_DB='lireddit'
NODE_ENV='development'
version: "3.6"
services:
  web:
    build: ./server/
    volumes:
      - server:/app
      - server_node_modules:/app/node_modules
    ports:
      - "4000:4000"
    depends_on:
      - postgres
    env_file:
      - .env
  postgres:
    image: postgres:13.2
    restart: always
    ports:
      - "5432:5432"
    volumes:
      - db_data:/var/lib/postgresql/data
    env_file:
      - .env

volumes:
  db_data:
  server:
    driver_opts:
      type: none
      device: ${PWD}/server
      o: bind
  server_node_modules:
    driver_opts:
      type: none
      device: ${PWD}/server/node_modules
      o: bind

Best Practices

  • Avoid Committing .env Files: Add .env to your .gitignore to prevent accidental commits.
  • Use Different .env Files for Different Environments: For example, .env.development, .env.production, and .env.test.
  • Load .env Files Automatically: Use tools like dotenv in Node.js projects to load environment variables in non-Docker environments.

Conclusion

Using .env files in docker-compose.yml simplifies environment variable management, making your setup more flexible and maintainable. By keeping credentials out of your version-controlled files and leveraging the env_file directive, you can efficiently manage configurations across multiple environments.