Environment variables precedence in Docker Compose

When you set the same environment variable in multiple sources, there’s a precedence rule used by Compose. It aims to resolve the value for the variable in question.

This page contains information on the level of precedence each method of setting environmental variables takes.

The order of precedence (highest to lowest) is as follows:

  1. Set using docker compose run -e in the CLI
  2. Substituted from your shell
  3. Set using the environment attribute in the Compose file
  4. Use of the --env-file argument in the CLI
  5. Use of the env_file attribute in the Compose file
  6. Set using an .env file placed at base of your project directory
  7. Set in a container image in the ENV directive. Having any ARG or ENV setting in a Dockerfile evaluates only if there is no Docker Compose entry for environment, env_file or run --env.

Simple example

In the example below, we set a different value for the same environment variable in an .env file and with the environment attribute in the Compose file:

$ cat ./Docker/api/api.env

$ cat compose.yml
    image: 'node:6-alpine'
     - ./Docker/api/api.env
     - NODE_ENV=production

The environment variable defined with the environment attribute takes precedence.

$ docker compose exec api node

> process.env.NODE_ENV

Hard coding variables in container scripts

Executing a command within the container that unconditionally sets a variable value overrules any setting in your compose.yml file.

For example, in a NodeJS project, if you have a package.json entry for scripts.start, such as NODE_ENV=test node server.js, any value set for NODE_ENV in your Compose file, is ignored when running npm run start within the container.

Advanced example

The following table uses TAG, an environment variable defining the version for an image, as an example.

How the table works

Each column represents a context from where you can set a value, or substitute in a value for TAG.

The columns Host OS environment and .env file is listed only as an illustration lookup. In reality, they don't result in a variable in the container by itself.

Each row represents a combination of contexts where TAG is set, substituted, or both.

#docker compose run --envenvironment attributeenv_file attributeImage ENVHost OS environment.env fileResult