In addition to the default .env file located in the project root, we can specify env files as follows:
- Using the
--env-file
CLI option - By defining the
env_file
attribute in the docker compose file itself
env_file vs --env-file
Regrading the env_file
attribute, the docker documentation states:
With this option, environment variables declared in the file cannot then be referenced again separately in the Compose file or used to configure Compose.
In essence, the --env-file
option can be used to make key-value pairs available to both the compose file itself and also to the container.
In contrast, the env_file
can only be used to make key-value pairs available as environment variables to the container.
The contents of the common.env
referred to in the following sections are as follows:
BASE_VOLUME_DIRECTORY=/mnt/primary-storage/docker-volumes/
FIRST_PROGRAM=HELLO-WORLD
--env-file
Consider the following docker compose file which will print out the available environment variables in the container:
version: "3.9"
services:
demo:
image: alpine:latest
command: [ "sh", "-c", "env" ]
environment:
- FIRST_PROGRAM
- SECOND_PROGRAM=${FIRST_PROGRAM}
- BASE_VOLUME_DIRECTORY=${BASE_VOLUME_DIRECTORY}
When using the --env-file
option, the key-value pairs will be available to the compose file itself.
Consequently, the variables defined in the enviroment
section will be set based on the contents of the env file and thus will be made available to the container as well.
Run the container as follows:
#!/usr/bin/env bash
docker compose --env-file=/path/to/common.env up
The output will include the following
...
FIRST_PROGRAM=HELLO-WORLD
SECOND_PROGRAM=HELLO-WORLD
BASE_VOLUME_DIRECTORY=/mnt/primary-storage/docker-volumes
...
env_file
On the other hand, if you specify an env file via the env_file
attribute as follows:
version: "3.9"
services:
demo:
image: alpine:latest
env_file:
- /path/to/common.env
command: [ "sh", "-c", "env" ]
environment:
- SECOND_PROGRAM=${FIRST_PROGRAM}
Then the environment variable SECOND_PROGRAM
will be set to empty as FIRST_PROGRAM
is not available to the compose file itself while BASE_VOLUME_DIRECTORY
& FIRST_PROGRAM
will be available to the container as expected.
When you run the container:
#!/usr/bin/env bash
docker compose up
Docker will first display a warning message for FIRST_PROGRAM
:
WARN[0000] The "FIRST_PROGRAM" variable is not set. Defaulting to a blank string.
Recall however that while FIRST_PROGRAM
is not available to the compose file it will still be available to the container.
As such, the container will show an empty value for SECOND_PROGRAM
while FIRST_PROGRAM
& BASE_VOLUME_DIRECTORY
will be set as expected i.e.
...
FIRST_PROGRAM=HELLO-WORLD
SECOND_PROGRAM=
BASE_VOLUME_DIRECTORY=/mnt/primary-storage/docker-volumes
...
Portainer
Global Environment Variables and Using the env_file attribute
Suppose that there are some environment variables that are common to all the docker compose files in your setup. For instance, the base path on the host for bind mounts might be the same everywhere.
Typically, the --env-file
option could be used to point to an env file containing all the common key-value pairs. However, if we run the portainer container with the environment variables specified, then those environment variables will be available to any docker compose based portainer stack definition:
Additionally, to use the env_file
attribute in the stack definitions we will have to specify the container path for the env files which will require mounting the directory containing the env files.
Given the docker compose file for portainer below:
# See Portainer Community Edition Installation for more details: https://docs.portainer.io/start/install-ce/server/docker/linux
version: "3.9"
services:
portainer:
image: "portainer/portainer-ce:latest"
container_name: "portainer"
ports:
- "8000:8000"
- "9443:9443"
restart: "unless-stopped"
security_opt:
- no-new-privileges:true
environment:
# Specify any environment variables that you want to be available to all stacks here
- FIRST_PROGRAM=${FIRST_PROGRAM}
- BASE_VOLUME_DIRECTORY=${BASE_VOLUME_DIRECTORY}
volumes:
- "/etc/localtime:/etc/localtime:ro"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "$BASE_VOLUME_DIRECTORY/env-files:/env-files:ro"
- "$BASE_VOLUME_DIRECTORY/portainer/data:/data"
We can run the portainer container as follows:
!/usr/bin/env bash
docker compose --env-file=/path/to/common.env up -d
We can verify that everything is working as expected by creating a stack with the following definition:
version: "3.9"
services:
demo:
image: alpine:latest
env_file:
- /env-files/demo.env
environment:
- FIRST_PROGRAM
- SECOND_PROGRAM=${FIRST_PROGRAM}
- BASE_VOLUME_DIRECTORY=${BASE_VOLUME_DIRECTORY}
command: [ "sh", "-c", "env" ]
Assume that another env file demo.env
exists in the /env-files
directory as follows:
DEMO_TITLE=ENVIRONMENT-VARIABLES-DEMO
We should see the following log output:
...
FIRST_PROGRAM=HELLO-WORLD
SECOND_PROGRAM=HELLO-WORLD
DEMO_TITLE=ENVIRONMENT-VARIABLES-DEMO
BASE_VOLUME_DIRECTORY=/mnt/primary-storage/docker-volumes
...
References / Additional Reading
- “Environment Variables Precedence in Docker Compose.” Docker Documentation, docs.docker.com/compose/environment-variables/envvars-precedence/.
- “Stacks = Docker-Compose, the Portainer Way.”, Portainer, www.portainer.io/blog/stacks-docker-compose-the-portainer-way.
- “Using Env Files in Stacks with Portainer.”, Portainer, www.portainer.io/blog/using-env-files-in-stacks-with-portainer.
- “Ways to Set Environment Variables in Compose.” Docker Documentation, docs.docker.com/compose/environment-variables/set-environment-variables
Docker Compose ENV Files and Portainer
Explore the nuances of Docker Compose environment variables by understanding the differences between the --env-file CLI option and env_file attribute. Also learn how to set global environment variables and how to use the env_file attribute with Portainer stacks.