57

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?

2
  • When do you want ./script/that/gets/var to run? Docker files are for build time. If you want something to run at container boot time, just create a script that runs ./script/that/gets/var and then the main command. Commented Dec 30, 2014 at 19:58
  • 1
    I want it to run at build time and create environment variables that will be present at run time. Commented Dec 30, 2014 at 20:00

3 Answers 3

35

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".

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
Sign up to request clarification or add additional context in comments.

4 Comments

Re: "The purpose of docker images to be very consistent", I get that but this is specifically about the container, which has all kinds of dynamic stuff going on.
The problem with the template approach for my use case is that app is running on Elastic Beanstalk and the build step is controlled by the service so I can't get my template compiled in the place I actually care about it (though it would certainly solve this problem for other use cases).
@Evan hear hear, tough problem. Then the answer is: no - you are not missing anything obvious and it is not possible ;)
Well at least I can feel good about my research before posting this :) Here, have a check mark.
33

Docker 1.9 has added support for build time arguments.

In your Dockerfile, you add an ARG statement, which has a similar syntax to ENV.

ARG FOO_REQUIRED
ARG BAR_OPTIONAL=something

At build time, you can pass pass a --build-arg argument to set the argument for that build. Any ARG that was not given a default value in the Dockerfile must be specified.

$ docker build --build-arg FOO_REQUIRED=best-foo-ever .

1 Comment

Side question ... how is this passed to a build on elastic beanstalk? AFAIK you can't provide a build command to a docker deployment on Elastic Beanstalk.
4

To build ENV VAR_NAME $(./script/that/gets/var) into the container, create a dynamic Dockerfile at build time:

$ docker build -t awesome -f Dockerfile .
$ # get VAR_NAME value: 
$ VAR_VALUE=`docker run --rm awesome \
    bash -c 'echo $(./script/that/gets/var)'`
$ # use dynamic Dockerfile:
$ {
     echo "FROM awesome"
     echo "ENV VAR_NAME $VAR_VALUE"
   } | docker build -t awesome -

https://github.com/42ua/docker-autobuild/blob/master/emscripten-sdk/README.md#build-docker-image

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.