Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create dynamic environment variables at build time in Docker

Tags:

docker

My specific use case is that I want to organize some data about the EC2 instance a container is running on and make i available as an environment variable. I'd like to do this when the container is built.

I was hoping to be able to do something like ENV VAR_NAME $(./script/that/gets/var) in my Dockerfile, but unsurprisingly that does not work (you just get the string $(./script...).

I should mention that I know the docker run --env... will do this, but I specifically want it to be built into the container.

Am I missing something obvious? Is this even possible?

like image 242
Evan Avatar asked Dec 30 '14 19:12

Evan


People also ask

How do I set an environment variable in docker?

Use -e or --env value to set environment variables (default []). If you want to use multiple environments from the command line then before every environment variable use the -e flag. Note: Make sure put the container name after the environment variable, not before that.

Can environment variables be dynamic?

Dynamic environment variables are read-only and are computed each time the variable is expanded. When all variables are listed with SET, these will not appear in the list.

Does docker build .ENV files?

If you are using docker-compose (which now comes bundled with Docker), . env is the default filename for the file that contains variables that are made available to the parser for the docker-compose. yml file ONLY, and not to the build process or container environment variables.

What is the correct way to pass an argument with a value during docker build phase?

If you want to pass multiple build arguments with docker build command you have to pass each argument with separate — build-arg. docker build -t <image-name>:<tag> --build-arg <key1>=<value1> --build-arg <key2>=<value2> .


1 Answers

Docker v1.9 or newer

If you are using Docker v1.9 or newer, this is possible via support for build time arguments. Arguments are declared in the Dockerfile by using the ARG statement.

ARG REQUIRED_ARGUMENT ARG OPTIONAL_ARGUMENT=default_value 

When you later actually build your image using docker build you can pass arguments via the flag --build-arg as described in the docker docs.

$ docker build --build-arg REQUIRED_ARGUMENT=this-is-required . 

Please note that it is not recommended to use build-time variables for passwords or secrets such as keys or credentials.

Furthermore, build-time variables may have great impact on caching. Therefore the Dockerfile should be constructed with great care to be able to utilize caching as much as possible and therein speed up the building process.

Edit: the "docker newer than v1.9"-part was added after input from leedm777:s answer.


Docker before v1.9

If you are using a Docker-version before 1.9, the ARG/--build-arg approach was not possible. You couldn't resolve this kind of info during the build so you had to pass them as parameters to the docker run command.

Docker images are to be consistent over time whereas containers can be tweaked and considered as "throw away processes".

  • More info about ENV
  • A docker discussion about dynamic builds

The old solution to this problem was to use templating. This is not a neat solution but was one of very few viable options at the time. (Inspiration from this discussion).

  1. save all your dynamic data in a json or yaml file
  2. create a docker file "template" where the dynamic can later be expanded
  3. write a script that creates a Dockerfile from the config data using some templating library that you are familiar with
like image 82
wassgren Avatar answered Oct 22 '22 01:10

wassgren