Skip to main content

[SOLVED] How can I use environment variables in docker-compose? - docker

[SOLVED] Mastering Environment Variables in Docker Compose: A Simple Guide

In this article, we will look at ways to use environment variables in Docker Compose. Environment variables are very important. They help us set up containers in a flexible way. This makes it easier to manage our applications. When we understand how to use environment variables in our docker-compose.yml file, we can make our work better. This also helps our applications work well in different places.

We will talk about these ways to manage environment variables in Docker Compose:

  • Solution 1: Defining Environment Variables in docker-compose.yml
  • Solution 2: Using an .env File for Environment Variables
  • Solution 3: Passing Environment Variables from the Host System
  • Solution 4: Overriding Environment Variables in Docker Compose
  • Solution 5: Accessing Environment Variables in Dockerfile
  • Solution 6: Using Variable Substitution in Docker Compose

By the end of this guide, we will understand how to use these techniques. This will help us improve our Docker Compose setup a lot.

For more information on similar topics, you can check how to pass environment variables in Docker or learn about using Docker Compose. Now let’s start with each solution!

Solution 1 - Defining Environment Variables in docker-compose.yml

We can define environment variables directly in our docker-compose.yml file. We use the environment key under the service settings. This way, we can set environment variables for the containers while they run.

Here is how we can do it:

version: "3.8"

services:
  web:
    image: nginx:latest
    environment:
      - MY_ENV_VAR=some_value
      - ANOTHER_VAR=another_value

In this example, the web service uses the Nginx image. We define two environment variables: MY_ENV_VAR and ANOTHER_VAR.

More Complex Example

We can also define environment variables using a dictionary format. This makes it easier to read and allows us to use values that have special characters:

version: "3.8"

services:
  app:
    image: my_app_image
    environment:
      MY_ENV_VAR: "some_value"
      ANOTHER_VAR: "complex value with spaces"
      SECRET_KEY: ${SECRET_KEY} # Reference a variable from the host or .env

Important Notes:

  • If we reference an environment variable like SECRET_KEY, we must make sure it’s defined in our host environment or in an .env file.
  • This way is simple and works good for small projects or setups.

For more advanced settings, we can think about using an .env file or other ways to pass environment variables. We can read more about these options in the next solutions below.

Solution 2 - Using an .env File for Environment Variables

Using an .env file is one easy and common way to manage environment variables in Docker Compose. This method helps us keep our docker-compose.yml tidy and easy to work with.

Steps to Use an .env File

  1. Create an .env File: In our project folder, we need to make a file called .env. This file will have our environment variables written as KEY=VALUE.

    Example of an .env file:

    DB_HOST=db
    DB_USER=root
    DB_PASSWORD=secret
  2. Reference the Variables in docker-compose.yml: In our docker-compose.yml file, we can use the variables from the .env file by writing them like this ${VARIABLE_NAME}.

    Example of a docker-compose.yml:

    version: "3.8"
    
    services:
      db:
        image: mysql:latest
        environment:
          MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
          MYSQL_DATABASE: mydatabase
        ports:
          - "3306:3306"
    
      app:
        image: myapp:latest
        environment:
          DATABASE_URL: mysql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}/mydatabase
        depends_on:
          - db
  3. Start Your Services: We can run this command in the terminal to start our Docker Compose services. Docker Compose will find the environment variables in the .env file.

    docker-compose up -d

Benefits of Using an .env File

  • Separation of Concerns: It keeps our environment settings separate from the app code.
  • Easy to Manage: It makes managing environment variables easier, especially when applications get complex.
  • Version Control: We can add the .env file to our version control system. But we should keep it out of public repositories for safety.

Best Practices

  • Exclude Sensitive Data: We must make sure to not put sensitive data in version control. We can add the .env file to our .gitignore.
  • Use Default Values: It is good to provide default values in our docker-compose.yml for better fallback options.
  • Document Your Variables: It helps to write down what each variable is for in our .env file for later.

Using an .env file for environment variables in Docker Compose makes our setup easier and improves security and maintenance. For more tips on Docker Compose, we can check this article on how to pass environment variables.

Solution 3 - Passing Environment Variables from the Host System

We can pass environment variables from our host system to our Docker containers defined in docker-compose.yml. This way, we can use existing environment variables on our host. It also helps keep sensitive data, like passwords or API keys, out of our configuration files.

Using Environment Variables in docker-compose.yml

To pass environment variables from our host system, we can reference them in our docker-compose.yml file using the ${VARIABLE_NAME} format. Let’s see how to do it:

  1. Define the Environment Variable on the Host: First, we need to set the environment variable in our terminal or in our shell configuration file, like .bashrc or .zshrc. For example:

    export MY_ENV_VAR="SomeValue"
  2. Reference the Environment Variable in docker-compose.yml: Next, we use the variable in our docker-compose.yml file like this:

    version: "3.8"
    
    services:
      my_service:
        image: my_image
        environment:
          - MY_ENV_VAR=${MY_ENV_VAR}
  3. Run Docker Compose: When we run docker-compose up, Docker will automatically use the value of MY_ENV_VAR from our host in the container.

Example

Here is a full example that shows this process:

  1. Set the Environment Variable:

    export DATABASE_URL="mysql://user:password@localhost:3306/mydb"
  2. docker-compose.yml Configuration:

    version: "3.8"
    
    services:
      db:
        image: mysql:5.7
        environment:
          - MYSQL_ROOT_PASSWORD=root
          - MYSQL_DATABASE=mydb
          - DATABASE_URL=${DATABASE_URL}
        ports:
          - "3306:3306"

In this example, the DATABASE_URL environment variable from the host will go into the db service when we run docker-compose up.

Important Notes

  • If we do not set the variable on the host, Docker Compose will send an empty string to the container. We can also give a default value like this: ${MY_ENV_VAR:-default_value}.
  • We should make sure our environment variables do not clash with existing variables in the container.
  • For sensitive info, we can use Docker secrets or an external tool for secrets management instead of passing them through environment variables.

For more details on managing environment variables in Docker, we can check out this guide.

Solution 4 - Overriding Environment Variables in docker-compose

In Docker Compose, we can easily change environment variables that we set in our docker-compose.yml file. This is very helpful when we want to adjust the setup for different places like development, testing, or production without changing the main setup.

To change environment variables in Docker Compose, we can use these methods:

  1. Using the command line: We can set environment variables right in the command line when we run the docker-compose command. We do this by adding the variable before the command.

    MY_ENV_VAR=value docker-compose up

    In our docker-compose.yml, we can use MY_ENV_VAR like this:

    version: "3"
    services:
      my_service:
        image: my_image
        environment:
          - MY_ENV_VAR=${MY_ENV_VAR}
  2. Using an .env file: We can use the .env file to set default values for environment variables. But if we set the same variable in the command line, it will take priority over the one in the .env file.

    We should create a .env file in the same folder as our docker-compose.yml:

    MY_ENV_VAR=default_value

    Then, we can reference it in our docker-compose.yml:

    version: "3"
    services:
      my_service:
        image: my_image
        environment:
          - MY_ENV_VAR

    To change it, we just run:

    MY_ENV_VAR=new_value docker-compose up
  3. Using docker-compose.override.yml: Docker Compose looks for a file called docker-compose.override.yml. This file can change or override settings from the main docker-compose.yml. For example:

    docker-compose.override.yml:

    version: "3"
    services:
      my_service:
        environment:
          - MY_ENV_VAR=new_override_value

    When we run docker-compose up, Docker Compose will combine the setups and use the new value of MY_ENV_VAR.

  4. Specifying values in a specific Compose file: We can also make several Compose files and say which one to use with the -f option. For example, we might have a docker-compose.prod.yml for production settings and environment variables:

    version: "3"
    services:
      my_service:
        image: my_image
        environment:
          - MY_ENV_VAR=prod_value

    We can run it with:

    docker-compose -f docker-compose.yml -f docker-compose.prod.yml up

In short, we can change environment variables in Docker Compose using the command line, an .env file, a separate override YAML file, or by using multiple Compose files. This gives us the freedom to manage different setups easily. For more help on using environment variables in Docker Compose, check this link.

Solution 5 - Accessing Environment Variables in Dockerfile

In Docker, we need to access environment variables in a Dockerfile. This is important for setting up our application and changing how it works during the build. We can define these environment variables in the Dockerfile with the ENV command. Then, we can use them in our application when it runs.

Defining Environment Variables

To define an environment variable in a Dockerfile, we use this format:

ENV VARIABLE_NAME=value

For example, if we want to set a variable called APP_ENV to production, we add this line to our Dockerfile:

ENV APP_ENV=production

Accessing Environment Variables

After we define environment variables in the Dockerfile, we can access them in our application code using methods specific to the programming language. For example:

  • In a Node.js application:
const appEnv = process.env.APP_ENV; // Accessing the APP_ENV variable
console.log(`The application is running in ${appEnv} mode.`);
  • In a Python application:
import os

app_env = os.getenv('APP_ENV')  # Accessing the APP_ENV variable
print(f'The application is running in {app_env} mode.')

Using Build Arguments

If we want to pass changing values when we build, we can use build arguments with the ARG command. For example:

ARG APP_VERSION
ENV VERSION=${APP_VERSION}

Then, we can build our Docker image with this command:

docker build --build-arg APP_VERSION=1.0 -t my-app .

This command sets the VERSION environment variable in the Docker image based on the APP_VERSION we provide while building.

Best Practices

  • Combine ENV and ARG: We should use ARG for values we need at build time and ENV for values we need when the application runs. This helps us keep our Dockerfile clean.

  • Document Variables: We should add comments about our environment variables in the Dockerfile to explain what they do.

  • Avoid Sensitive Information: We must not put sensitive information like passwords directly in the Dockerfile. We can use a secrets management tool or pass them as environment variables when the application runs.

Example Dockerfile

Here is a complete example of a Dockerfile that shows how to use environment variables:

# Use a base image
FROM python:3.9-slim

# Set environment variables
ENV APP_ENV=production
ENV VERSION=1.0

# Set a working directory
WORKDIR /app

# Copy application files
COPY . .

# Install dependencies
RUN pip install -r requirements.txt

# Command to run the application
CMD ["python", "app.py"]

In this example, the Dockerfile sets environment variables for the application. It uses them in the application code. This helps us make our Docker images more flexible and easy to configure.

For more details about using Dockerfiles, we can check this article on Dockerfile configuration.

Solution 6 - Using Variable Substitution in docker-compose

We can use variable substitution in docker-compose to define values that change. This means we can use environment variables or other variables in our docker-compose.yml file. This feature helps us be more flexible. It lets us manage different environments like development, testing, and production easily.

Basic Syntax

In a docker-compose.yml file, we can use variable substitution by putting the variable name in ${}. For example:

version: "3.8"
services:
  web:
    image: ${WEB_IMAGE:-myapp:latest} # Default is 'myapp:latest' if WEB_IMAGE is not set
    ports:
      - "${WEB_PORT:-80}:80" # Default is port 80 if WEB_PORT is not set

Defining Variables

We can define variables in a few ways:

  1. Environment Variables: We can set environment variables in our shell before we run docker-compose:

    export WEB_IMAGE=myapp:production
    export WEB_PORT=8080
    docker-compose up
  2. .env File: We can create a .env file in the same folder as our docker-compose.yml. The file can have key-value pairs for our variables:

    WEB_IMAGE=myapp:production
    WEB_PORT=8080

    docker-compose reads this file automatically when it runs.

  3. Inline Variables: We can also give variables inline when we run docker-compose:

    WEB_IMAGE=myapp:production WEB_PORT=8080 docker-compose up

Using Variable Substitution

When we use variable substitution, the syntax ${VARIABLE_NAME} lets us use the defined environment variables directly in the docker-compose.yml. We can use this for images, ports, volumes, and other options that support substitution.

Here is an example to show variable substitution in a full service definition:

version: "3.8"
services:
  app:
    image: ${APP_IMAGE:-myapp:latest}
    environment:
      - NODE_ENV=${NODE_ENV:-development}
    ports:
      - "${APP_PORT:-3000}:3000"
    volumes:
      - ${APP_DATA_DIR:-./data}:/data

In this example:

  • The APP_IMAGE variable decides which image to use for the app.
  • The NODE_ENV variable sets the environment variable inside the container.
  • The APP_PORT variable allows us to change the port.
  • The APP_DATA_DIR variable lets us set a data folder that can be mapped to the container.

Important Notes

  • If we do not define a variable, we can give a default value using ${VARIABLE:-default_value}.
  • Be careful with variable names to not conflict with Docker Compose internal variables.
  • For more details on docker-compose variable substitution, you can check the official docker-compose documentation.

By using variable substitution in docker-compose, we can make our configuration more flexible and easier to manage. It helps us adapt to different deployment situations In conclusion, we have looked at different ways to use environment variables in Docker Compose. We talked about defining them directly in docker-compose.yml. We also discussed using an .env file and passing them from the host system.

Knowing these methods helps us manage our containerized apps better. It also helps us keep our settings clean and flexible.

For more tips on Docker, you can check our guides on how to manage Docker Compose and the importance of environment variables in Docker.

Comments