Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I set environment variables during the build in docker

ARG is for setting environment variables which are used during the docker build process - they are not present in the final image, which is why you don't see them when you use docker run.

You use ARG for settings that are only relevant when the image is being built, and aren't needed by containers which you run from the image. You can use ENV for environment variables to use during the build and in containers.

With this Dockerfile:

FROM ubuntu                                                                                                            
ARG BUILD_TIME=abc                                                                                                     
ENV RUN_TIME=123                                                                                                       
RUN touch /env.txt                                                                                                     
RUN printenv > /env.txt 

You can override the build arg as you have done with docker build -t temp --build-arg BUILD_TIME=def .. Then you get what you expect:

> docker run temp cat /env.txt                                                                                         
HOSTNAME=b18b9cafe0e0                                                                                                  
RUN_TIME=123                                                                                                           
HOME=/root                                                                                                             
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin                                                      
BUILD_TIME=def                                                                                                         
PWD=/ 

I'll summarize highlights from this great article.


ARG Vs ENV

1 ) Short explanation:
ARG is only available during the build of a Docker image (RUN etc), not after the image is created and containers are started from it (ENTRYPOINT, CMD).

ENV values are available to containers, but also RUN-style commands during the Docker build starting with the line where they are introduced. If you set an environment variable in an intermediate container using bash (RUN export VARI=5 && …) it will not persist in the next command.

2 ) Longer explanation:
ARG are also known as build-time variables. They are only available from the moment they are ‘announced’ in the Dockerfile with an ARG instruction up to the moment when the image is built. Running containers can’t access values of ARG variables. This also applies to CMD and ENTRYPOINT instructions which just tell what the container should run by default. If you tell a Dockerfile to expect various ARG variables (without a default value) but none are provided when running the build command, there will be an error message.

However, ARG values can be easily inspected after an image is built, by viewing the docker history of an image. Thus they are a poor choice for sensitive data.

ENV variables are also available during the build, as soon as you introduce them with an ENV instruction. However, unlike ARG, they are also accessible by containers started from the final image. ENV values can be overridden when starting a container, more on that below.

3 ) With diagrem:
Here is a simplified overview of ARG and ENV availabilities around the process around building a Docker image from a Dockerfile, and running a container.

They overlap, but ARG is not usable from inside the containers.

enter image description here

Setting ARG and ENV values

Setting ARG values

So, you have your Dockerfile, which defines ARG and ENV values. How to set them, and where? You can leave them blank in the Dockerfile, or set default values. If you don’t provide a value to expected ARG variables which don’t have a default, you’ll get an error message.

Here is a Dockerfile example, both for default values and without them:

ARG some_variable_name
# or with a hard-coded default:
#ARG some_variable_name=default_value

RUN echo "Oh dang look at that $some_variable_name"
# you could also use braces - ${some_variable_name}

When building a Docker image from the commandline, you can set ARG values using –build-arg:

$ docker build --build-arg some_variable_name=a_value

Running that command, with the above Dockerfile, will result in the following line being printed (among others): Oh dang look at that a_value

So, how does this translate to using docker-compose.yml files?
When using docker-compose, you can specify values to pass on for ARG, in an args block:
(docker-compose.yml file)

version: '3'

services:
  somename:
    build:
      context: ./app
      dockerfile: Dockerfile
      args:
        some_variable_name: a_value

When you try to set a variable which is not ARG mentioned in the Dockerfile, Docker will complain.

Setting ENV Values

So, how to set ENV values? You can do it when starting your containers (and we’ll look at this a bit below), but you can also provide default ENV values directly in your Dockerfile by hard-coding them. Also, you can set dynamic default values for environment variables!

When building an image, the only thing you can provide are ARG values, as described above. You can’t provide values for ENV variables directly. However, both ARG and ENV can work together. You can use ARG to set the default values of ENV vars.
Here is a basic Dockerfile, using hard-coded default values:

# no default value
ENV hey
# a default value
ENV foo /bar
# or ENV foo=/bar

# ENV values can be used during the build
ADD . $foo
# or ADD . ${foo}
# translates to: ADD . /bar

And here is a snippet for a Dockerfile, using dynamic on-build env values:

# expect a build-time variable
ARG A_VARIABLE
# use the value to set the ENV var default
ENV an_env_var=$A_VARIABLE
# if not overridden, that value of an_env_var will be available to your containers!

Once the image is built, you can launch containers and provide values for ENV variables in three different ways, either from the command line or using a docker-compose.yml file.
All of those will override any default ENV values in the Dockerfile.
Unlike ARG, you can pass all kinds of environment variables to the container. Even ones not explicitly defined in the Dockerfile.
It depends on your application whether that’ll do anything however.

Option 1: Provide values one by one
From the commandline, use the -e flag:

$ docker run -e "env_var_name=another_value" alpine env

From a docker-compose.yml file:

version: '3'

services:
  plex:
    image: linuxserver/plex
      environment:
        - env_var_name=another_value

Option 2: Pass environment variable values from your host
It’s the same as the above method.
The only difference is, you don’t provide a value, but just name the variable. This will make Docker access the current value in the host environment and pass it on to the container.

$ docker run -e env_var_name alpine env

For the docker-compose.yml file, leave out the equation sign and everything after it for the same effect.

version: '3'

services:
  plex:
    image: linuxserver/plex
      environment:
        - env_var_name

Option 3: Take values from a file (env_file)
Instead of writing the variables out or hard-coding them (not in good taste according to the 12-factor folks), we can specify a file to read values from. The contents of such a file look something like this:

env_var_name=another_value

The file above is called env_file_name (name arbitrary) and it’s located in the current directory.
You can reference the filename, which is parsed to extract the environment variables to set:

$ docker run --env-file=env_file_name alpine env

With docker-compose.yml files, we just reference a env_file, and Docker parses it for the variables to set.

version: '3'

services:
  plex:
    image: linuxserver/plex
    env_file: env_file_name

Common ways to set ARG and ENV from the command line

Here is a small cheat sheet, combining an overview of ARG and ENV availability with common ways to set them from the command line.

enter image description here