docker-compose is an amazing tool to create a full fledged environment using different docker containers. We have used the same in our case to deploy multiple environments for testing.
This article will share the best practices when it comes to using environments files inside docker-compose.yml
Approach #1 - Using env_file
Let’s create a simple docker-compose.yml
file which prints a environment variable and then sleeps for sometime
docker-compose.yml
version: '2'
services:
demo:
image: centos:7.2.1511
command: sh -c '/bin/echo "My name is $$NAME" && sleep 2000'
env_file:
- ./env.sh
Note we have used $$
instead of $
, as docker-compose itself does variable substitution
env.sh
NAME=TARUN
Run the composition using docker-compose up -d && docker-compose logs demo
vagrant@vagrant:/vagrant/docker-compose-environment$ docker-compose up -d && docker-compose logs demo
Creating network "dockercomposeenvironment_default" with the default driver
Creating dockercomposeenvironment_demo_1
Attaching to dockercomposeenvironment_demo_1
demo_1 | My name is TARUN
Now let us update the content of env.sh
env.sh
NAME=TARUN2
Let’s restart the demo container using docker-compose restart demo && docker-compose logs demo
vagrant@vagrant:/vagrant/docker-compose-environment$ docker-compose restart demo && docker-compose logs demo
Restarting dockercomposeenvironment_demo_1 ... done
Attaching to dockercomposeenvironment_demo_1
demo_1 | My name is TARUN
demo_1 | My name is TARUN
First message is from our previous run and last one from the restart. As you can see the environment variable don’t get picked up during restart if the environment file is updated.
Note: This approach is not recommended if you plan to restart your containers and want updated variables to be picked up
Approach 2 - Using volume file mapping
docker-compose.yml
We update our docker-compose.yml
to use file mapping instead
version: '2'
services:
demo:
image: centos:7.2.1511
command: sh -c '. /env/env.sh && /bin/echo "My name is $$NAME" && sleep 2000'
volumes:
- ./env.sh:/env/env.sh
Now let us retry the restart scenario
vagrant@vagrant:/vagrant/docker-compose-environment$ docker-compose up -d && docker-compose logs demo
Creating network "dockercomposeenvironment_default" with the default driver
Creating dockercomposeenvironment_demo_1
Attaching to dockercomposeenvironment_demo_1
demo_1 | My name is TARUN
vagrant@vagrant:/vagrant/docker-compose-environment$ vim env.sh
vagrant@vagrant:/vagrant/docker-compose-environment$ cat env.sh
NAME=TARUN2
vagrant@vagrant:/vagrant/docker-compose-environment$ docker-compose restart demo && docker-compose logs demo
Restarting dockercomposeenvironment_demo_1 ... done
Attaching to dockercomposeenvironment_demo_1
demo_1 | My name is TARUN
demo_1 | My name is TARUN2
As you can see now, we get the updated environment variables.
Approach 3 - Using volume folder mapping
I personally prefer this instead of using file mapping. Folder mapping allow us to place multiple environment files which may be required for different scripts
docker-compose.yml
version: '2'
services:
demo:
image: centos:7.2.1511
command: sh -c '. /env/env.sh && /bin/echo "My name is $$NAME" && sleep 2000'
volumes:
- ./env:/env
./env/env.sh
NAME=TARUN
The only change here being that we move our environment variables file env.sh
to the env
folder
Spacing in environment variables
There is suttle difference in Approach #1 and #2/#3, when it comes to spacing in envrionment variable values. Consider the below environment file
NAME="TARUN LALWANI"
See the different of outputs between Approach #1 and Approach #2
vagrant@vagrant:/vagrant/docker-compose-environment$ docker-compose -f docker-compose-approach1.yml up
Recreating dockercomposeenvironment_demo_1
Attaching to dockercomposeenvironment_demo_1
demo_1 | My name is "TARUN LALWANI"
^CGracefully stopping... (press Ctrl+C again to force)
Stopping dockercomposeenvironment_demo_1 ... done
vagrant@vagrant:/vagrant/docker-compose-environment$ docker-compose -f docker-compose-approach2.yml up
Recreating dockercomposeenvironment_demo_1
Attaching to dockercomposeenvironment_demo_1
demo_1 | My name is TARUN LALWANI
^CGracefully stopping... (press Ctrl+C again to force)
Stopping dockercomposeenvironment_demo_1 ... done
Note: Approach one will have double quotes
"
included as the part of the variable value, while #2 and #3 won’t
You can find the sample codes for this article on tarunlalwani/docker-compose-environment