Skip to main content

Environment Variables and Configuration Management

Introduction

As applications become more complex, managing their configuration becomes crucial, especially in containerized environments like Docker. Hardcoding sensitive or environment-specific information (such as database credentials or API keys) in images or code is insecure and inflexible. Instead, Docker provides mechanisms to inject configuration at runtime using environment variables and external configuration files. This lesson explores how to effectively manage environment variables and configuration in Docker containers.


Why Configuration Management Matters

  • Separation of concerns: Keeps configuration separate from application code.
  • Security: Prevents sensitive data from being baked into images.
  • Portability: Makes containers easily reusable across development, staging, and production environments.
  • Flexibility: Allows quick changes without rebuilding images.

Setting Environment Variables in Docker

Using the docker run Command

You can pass environment variables directly when starting a container:

docker run -e APP_ENV=production -e DEBUG=false mywebapp:latest
  • -e or --env: Sets an environment variable.

Example:

docker run -e MYSQL_ROOT_PASSWORD=supersecret mysql:8.0

Using Environment Files (--env-file)

You can store variables in a file and load them all at once:

.env file:

APP_ENV=production
DEBUG=false
SECRET_KEY=mysupersecretkey

Run with env file:

docker run --env-file .env mywebapp:latest

Benefits:

  • Easy to manage and version control (be careful with secrets!)
  • Keeps run commands clean

Defining Environment Variables in Dockerfiles

You can set default environment variables in your Dockerfile using the ENV instruction:

FROM node:18-alpine

ENV NODE_ENV=production
ENV PORT=3000

CMD ["node", "app.js"]

How it works:

  • These defaults can be overridden at runtime with docker run -e.

Accessing Environment Variables in Applications

Most programming languages provide access to environment variables. For example:

Node.js:

const port = process.env.PORT || 3000;
console.log(`Server running on port ${port}`);

Python:

import os
db_url = os.environ.get('DATABASE_URL', 'localhost')
print(f"Connecting to {db_url}")

Using Environment Variables in Docker Compose

Docker Compose supports environment variables for service configuration.

Option 1: Inline in docker-compose.yml

services:
web:
image: mywebapp:latest
environment:
- APP_ENV=production
- DEBUG=false

Option 2: Reference an .env File

  • By default, Compose looks for a file named .env in the project directory.

.env:

APP_ENV=production
DEBUG=false

docker-compose.yml:

services:
web:
image: mywebapp:latest
environment:
- APP_ENV
- DEBUG

Configuration Files and Secrets

While environment variables are convenient, they are not always ideal for large or sensitive configurations.

Mounting Configuration Files

You can mount configuration files as volumes:

docker run -v /host/config/app.conf:/app/app.conf mywebapp:latest

Use Case: Complex config files (e.g., YAML, JSON) or files required by application frameworks.

Managing Secrets

Best Practices:

  • Avoid putting secrets in images or code.
  • Use Docker Secrets (with Swarm) or external secret managers (e.g., HashiCorp Vault, AWS Secrets Manager).

Common Use Cases

  • Multiple environments: Set variables to distinguish between dev, staging, and prod.
  • Feature toggles: Enable or disable features via env vars.
  • Database connections: Pass DB credentials without hardcoding.
  • API keys: Inject third-party service keys at runtime.

Common Mistakes and Pitfalls

  • Hardcoding secrets in images: Never store passwords or keys directly in Dockerfiles.
  • Committing .env files with secrets: Use .gitignore to avoid accidental leaks.
  • Typos in variable names: Misspelled names can lead to unexpected application behavior.
  • Environment variable precedence: Variables set at runtime override Dockerfile defaults.
  • Exposing secrets via process listings: Avoid passing secrets as command-line arguments, as they can be visible in process listings.

Summary

  • Environment variables are the standard way to inject configuration into Docker containers.
  • Use -e, --env-file, or ENV in Dockerfile to set environment variables.
  • Docker Compose integrates environment variables seamlessly.
  • For sensitive or complex configuration, consider file mounts or secret management tools.
  • Avoid common mistakes like hardcoding secrets or committing them to version control.

Quiz

  1. Which of the following is NOT a recommended method for injecting sensitive data into a Docker container?

    a) docker run -e MYSQL_PASSWORD=supersecret mysql:8.0
    b) Using Docker Secrets with Swarm
    c) Baking passwords directly into the application code
    d) Mounting a secrets file as a volume

  2. How can you override an environment variable set in a Dockerfile at runtime?

    a) You cannot override it
    b) By using the -e flag in docker run
    c) By modifying the Dockerfile and rebuilding the image
    d) By changing the application code

  3. In Docker Compose, where does Compose look for environment variables by default?

    a) /etc/environment
    b) The .env file in the project directory
    c) /var/lib/docker/env
    d) The Dockerfile

  4. True or False: Environment variables set in a .env file are automatically available to all containers started with a docker run command.

  5. What is a potential security risk of passing secrets as command-line arguments to a container?

    a) The arguments can be seen in process listings
    b) They make the container run faster
    c) They are automatically encrypted
    d) They are stored in the container image


Answers

  1. c — Baking passwords directly into the application code is insecure and should be avoided.
  2. b — Use the -e flag to override environment variables at runtime.
  3. b — Docker Compose looks for a .env file in the project directory by default.
  4. False.env files are not used by docker run; they are used by Docker Compose or with --env-file.
  5. a — Secrets passed as command-line arguments can be visible to other users/processes on the host via process listings.