15

My current setup for running a docker container is on the lines of this:

  1. I've got a main.env file:
# Main
export PRIVATE_IP=\`echo localhost\`
export MONGODB_HOST="$PRIVATE_IP"
export MONGODB_URL="mongodb://$MONGODB_HOST:27017/development"
  1. In my service file (upstart), I source this file . /path/to/main.env

  2. I then call docker run with multiple -e for each of the environment variables I want inside of the container. In this case I would call something like: docker run -e MONGODB_URL=$MONGODB_URL ubuntu bash

  3. I would then expect MONGODB_URL inside of the container to equal mongodb://localhost:27017/development. Notice that in reality echo localhost is replaced by a curl to amazon's api for an actual PRIVATE_IP.

This becomes a bit unwieldy when you start having more and more environment variables you need to give your container. There is a fine point to see here which is that the environment variables need to be resolved at run time, such as with a call to curl or by referring to other env variables.

The solution I was hoping to use is:

  1. calling docker run with an --env-file parameter such as this:
# Main
PRIVATE_IP=\`echo localhost\`
MONGODB_HOST="$PRIVATE_IP"
MONGODB_URL="mongodb://$MONGODB_HOST:27017/development"
  1. Then my docker run command would be significantly shortened to docker run --env-file=/path/to/main.env ubuntu bash (keep in mind usually I've got around 12-15 environment variables.

This is where I hit my problem which is that inside the container none of the variables resolve as expected. Instead I end up with:

  • PRIVATE_IP=`echo localhost`
  • MONGODB_HOST="$PRIVATE_IP"
  • MONGODB_URL="mongodb://$MONGODB_HOST:27017/development"

I could circumvent this by doing the following:

  1. Sourcing the main.env file.
  2. Creating a file containing just the names of the variables I want (meaning docker would search for them in the environment).
  3. Then calling docker run with this file as an argument to --env-file. This would work but would mean I would need to maintain two files instead of one, and really wouldn't be that big of an improvement of the current situation.

What I would prefer is to have the variables resolve as expected.

The closest question to mine that I could find is: 12factor config approach with Docker

Community
  • 1
  • 1
rikonor
  • 409
  • 1
  • 4
  • 15
  • I noticed that your `main.env` is setting your vars as literal strings. Have you tried removing `"` & `'`? You can read more about how Docker handles literals here: https://docs.docker.com/reference/builder/#env – jakenberg Mar 17 '15 at 19:10
  • According to [docs](https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file) the env file syntax should be simple key=value items. Not sure how the 'export' would be handled in your case. – odedfos May 15 '18 at 07:21

7 Answers7

5
  • Ceate a .env file
 example: test=123 val=Guru
  • Execute command

docker run -it --env-file=.env bash

  • Inside the bash verify using

echo $test (should print 123)

Gurudath BN
  • 1,391
  • 20
  • 21
4

Both --env and --env-file setup variables as is and do not replace nested variables.

Solomon Hykes talks about configuring containers at run time and the the various approaches. The one that should work for you is to volume mounting the main.env from host into the container and sourcing it.

Philipp Kyeck
  • 18,402
  • 15
  • 86
  • 123
Usman Ismail
  • 17,999
  • 14
  • 83
  • 165
  • "sourcing it" means you need bash or some other shell and that means having lots of cruft in the container when, in my case, I just want the executable – Richard Aug 02 '17 at 13:59
4

So I just faced this issue as well, what solved it for me was I specified the --env-file or -e KEY=VAL before the name of the container image. For example

Broken:

docker run my-image --env-file .env

Fixed:

docker run --env-file .env my-image
Zach Bellay
  • 152
  • 2
  • 7
0

creating an ENV file that is nothing more than key/value pairs can be processed in normal shell commands and appended to the environment. Look at the bash -a pragma.

Richard
  • 10,122
  • 10
  • 42
  • 61
0

What you can do is create a startup script that can be run when the container starts. So if your current docker file looks something like this

From ...
...
CMD command

Change it to

From ...
...
ADD start.sh start.sh
CMD ["start.sh"]

In your start.sh script do the following:

export PRIVATE_IP=\`echo localhost\`
export MONGODB_HOST="$PRIVATE_IP"
export MONGODB_URL="mongodb://$MONGODB_HOST:27017/development"
command
yamenk
  • 46,736
  • 10
  • 93
  • 87
0

I had a very similar problem to this. If I passed the contents of the env file to docker as separate -e directives then everything ran fine however if I passed the file using --env-file the container failed to run properly.

Turns out there were some spurious line endings in the file (I had copied from windows and ran docker in Ubuntu). When I removed them the container ran the same with --env or --env-file.

Martin
  • 2,316
  • 1
  • 28
  • 33
0

I had this issue when using docker run in a separate run script run.sh file, since I wanted the credentials ADMIN_USER and ADMIN_PASSWORD to be accessible in the container, but not show up in the command.

Following the other answers and passing a separate environment file with --env or --env-file didn't work for my image (though it worked for the Bash image). What worked was creating a separate env file...

# env.list
ADMIN_USER='username'
ADMIN_PASSWORD='password'

...and sourcing it in the run script when launching the container:

# run.sh
source env.list
docker run -d \
    -e ADMIN_USER=$INFLUXDB_ADMIN_USER \
    -e ADMIN_PASSWORD=$INFLUXDB_ADMIN_PASSWORD \
    image_repo/name:tag
ascendants
  • 2,123
  • 3
  • 11
  • 22