Environment variables in Compose

Estimated reading time: 9 minutes

There are multiple parts of Compose that deal with environment variables in one sense or another. This page should help you find the information you need.

Substitute environment variables in Compose files

It’s possible to use environment variables in your shell to populate values inside a Compose file:

web:
  image: "webapp:${TAG}"

If you have multiple environment variables, you can substitute them by adding them to a default environment variable file named .env or by providing a path to your environment variables file using the --env-file command line option.

Your configuration options can contain environment variables. Compose uses the variable values from the shell environment in which docker-compose is run. For example, suppose the shell contains POSTGRES_VERSION=9.3 and you supply this configuration:

db:
  image: "postgres:${POSTGRES_VERSION}"

When you run docker-compose up with this configuration, Compose looks for the POSTGRES_VERSION environment variable in the shell and substitutes its value in. For this example, Compose resolves the image to postgres:9.3 before running the configuration.

If an environment variable is not set, Compose substitutes with an empty string. In the example above, if POSTGRES_VERSION is not set, the value for the image option is postgres:.

You can set default values for environment variables using a .env file, which Compose automatically looks for in project directory (parent folder of your Compose file). Values set in the shell environment override those set in the .env file.

Note when using docker stack deploy

The .env file feature only works when you use the docker-compose up command and does not work with docker stack deploy.

Both $VARIABLE and ${VARIABLE} syntax are supported. Additionally when using the 2.1 file format, it is possible to provide inline default values using typical shell syntax:

  • ${VARIABLE:-default} evaluates to default if VARIABLE is unset or empty in the environment.
  • ${VARIABLE-default} evaluates to default only if VARIABLE is unset in the environment.

Similarly, the following syntax allows you to specify mandatory variables:

  • ${VARIABLE:?err} exits with an error message containing err if VARIABLE is unset or empty in the environment.
  • ${VARIABLE?err} exits with an error message containing err if VARIABLE is unset in the environment.

Other extended shell-style features, such as ${VARIABLE/foo/bar}, are not supported.

You can use a $$ (double-dollar sign) when your configuration needs a literal dollar sign. This also prevents Compose from interpolating a value, so a $$ allows you to refer to environment variables that you don’t want processed by Compose.

web:
  build: .
  command: "$$VAR_NOT_INTERPOLATED_BY_COMPOSE"

If you forget and use a single dollar sign ($), Compose interprets the value as an environment variable and warns you:

The VAR_NOT_INTERPOLATED_BY_COMPOSE is not set. Substituting an empty string.

The “.env” file

You can set default values for any environment variables referenced in the Compose file, or used to configure Compose, in an environment file named .env. The .env file path is as follows:

  • Starting with +v1.28, .env file is placed at the base of the project directory
  • Project directory can be explicitly defined with the --file option or COMPOSE_FILE environment variable. Otherwise, it is the current working directory where the docker compose command is executed (+1.28).
  • For previous versions, it might have trouble resolving .env file with --file or COMPOSE_FILE. To work around it, it is recommended to use --project-directory, which overrides the path for the .env file. This inconsistency is addressed in +v1.28 by limiting the filepath to the project directory.
$ cat .env
TAG=v1.5

$ cat docker-compose.yml
version: '3'
services:
  web:
    image: "webapp:${TAG}"

When you run docker compose up, the web service defined above uses the image webapp:v1.5. You can verify this with the convert command, which prints your resolved application config to the terminal:

$ docker compose convert

version: '3'
services:
  web:
    image: 'webapp:v1.5'

Values in the shell take precedence over those specified in the .env file.

If you set TAG to a different value in your shell, the substitution in image uses that instead:

$ export TAG=v2.0
$ docker compose convert

version: '3'
services:
  web:
    image: 'webapp:v2.0'

You can override the environment file path using a command line argument --env-file.

Using the “--env-file” option

By passing the file as an argument, you can store it anywhere and name it appropriately, for example, .env.ci, .env.dev, .env.prod. Passing the file path is done using the --env-file option:

$ docker compose --env-file ./config/.env.dev up 

This file path is relative to the current working directory where the Docker Compose command is executed.

$ cat .env
TAG=v1.5

$ cat ./config/.env.dev
TAG=v1.6


$ cat docker-compose.yml
version: '3'
services:
  web:
    image: "webapp:${TAG}"

The .env file is loaded by default:

$ docker compose convert 
version: '3'
services:
  web:
    image: 'webapp:v1.5'

Passing the --env-file argument overrides the default file path:

$ docker compose --env-file ./config/.env.dev config 
version: '3'
services:
  web:
    image: 'webapp:v1.6'

When an invalid file path is being passed as --env-file argument, Compose returns an error:

$ docker compose --env-file ./doesnotexist/.env.dev  config
ERROR: Couldn't find env file: /home/user/./doesnotexist/.env.dev

For more information, see the Variable substitution section in the Compose file reference.

Set environment variables in containers

You can set environment variables in a service’s containers with the ‘environment’ key, just like with docker run -e VARIABLE=VALUE ...:

web:
  environment:
    - DEBUG=1

Pass environment variables to containers

You can pass environment variables from your shell straight through to a service’s containers with the ‘environment’ key by not giving them a value, just like with docker run -e VARIABLE ...:

web:
  environment:
    - DEBUG

The value of the DEBUG variable in the container is taken from the value for the same variable in the shell in which Compose is run.

The “env_file” configuration option

You can pass multiple environment variables from an external file through to a service’s containers with the ‘env_file’ option, just like with docker run --env-file=FILE ...:

web:
  env_file:
    - web-variables.env

Set environment variables with ‘docker compose run’

Similar to docker run -e, you can set environment variables on a one-off container with docker compose run -e:

$ docker compose run -e DEBUG=1 web python console.py

You can also pass a variable from the shell by not giving it a value:

$ docker compose run -e DEBUG web python console.py

The value of the DEBUG variable in the container is taken from the value for the same variable in the shell in which Compose is run.

When you set the same environment variable in multiple files, here’s the priority used by Compose to choose which value to use:

  1. Compose file
  2. Shell environment variables
  3. Environment file
  4. Dockerfile
  5. Variable is not defined

In the example below, we set the same environment variable on an Environment file, and the Compose file:

$ cat ./Docker/api/api.env
NODE_ENV=test

$ cat docker-compose.yml
version: '3'
services:
  api:
    image: 'node:6-alpine'
    env_file:
     - ./Docker/api/api.env
    environment:
     - NODE_ENV=production

When you run the container, the environment variable defined in the Compose file takes precedence.

$ docker compose exec api node

> process.env.NODE_ENV
'production'

Having any ARG or ENV setting in a Dockerfile evaluates only if there is no Docker Compose entry for environment or env_file.

Specifics for NodeJS containers

If you have a package.json entry for script:start like NODE_ENV=test node server.js, then this overrules any setting in your docker-compose.yml file.

Configure Compose using environment variables

Several environment variables are available for you to configure the Docker Compose command-line behavior. They begin with COMPOSE_ or DOCKER_, and are documented in CLI Environment Variables.

compose, orchestration, environment, env file