Puzzled Around ARG ENV and .env in Dockerfile
Tags: docker, tutorial, devops
Published: 2020-01-19 07:58:39

Yash Shah

##### Prerequisite :- Basic understanding of Dockerfile

Recently I came to a use case where i had to build image on the basis of params which depend on the environment i am currently building my container. Hence i use ARG to pass Arguments while building the container. And setting up ENV on the basis of ARG that i have provided.

### The .env file

It works with docker-compose.yml. You can simple use $ notation in your compose file to pick value from .env, if both docker-compose.yml and .env is in same directory

The **.env** looks something like this

```
first_variable=a
second_variable=b
```

The key-value pair is used in docker-compose.yml by simply using $ notation within the docker-compose.yml file. Lets look and example.

```
services:
  demo:
    image: linuxserver/demo
      environment:
        - env_var_name=${first_variable}    # here it is


```


###### 1. To check thing are working fine in docker-compose.yml you can simply use docker-compose config, This way you can check how your docker-compose.yml will look after substituting values from .env

###### 2. There is a glitch the environment variable in host machine can override the variable in your .env file


### Different types of variable in Dockerfile

ARG : ARG also known as build time variable, there availability is available the moment they are announced in the dockerfile till the docker image is build. Somewhat like CMD and ENTRYPOINT which tells the container what to 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

ENV: ENV are available during the run time, you can also override them during run time.

### How to use ARG variables 

So if you have a Dockerfile and if you want to set them? You can set them blank or leave a default value and you can override them during the docker build.

```
FROM ubuntu:18.04
ARG any_default_variable
# or with a hard-coded default:
#ARG any_default_variable=any_default_value

RUN echo "Hi $any_default_variable"
# you could also use braces - ${any_default_variable}


```

You can use the docker build command to send the build args 

```
docker build -t demo --build-arg any_default_variable=yash  .

```

The above command will produce the following output

```
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM ubuntu:18.04
 ---> ccc6e87d482b
Step 2/3 : ARG any_default_variable
 ---> Running in ec62ad011b88
Removing intermediate container ec62ad011b88
 ---> 3d8df126a04c
Step 3/3 : RUN echo "Hi $any_default_variable"
 ---> Running in e9f5fb20897e
Hi yash
Removing intermediate container e9f5fb20897e
 ---> d6fe8d6e0f9a
Successfully built d6fe8d6e0f9a
Successfully tagged demo:latest

```

### How to use ENV variables 

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

#### Setting up ENV variables

 You can do it when starting your containers, 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.


#### 1. Provide values one by one

From the commandline, use the -e flag:


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

```

#### 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

```

#### 3. Take values from a file (env_file)

The file 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

```

if you’re new to Docker and not used to think about images and containers: if you try to set the value of an environment variable from inside a RUN statement like RUN export VARI=5 && ..., you won’t have access to it in any of the next RUN statements. The reason for this, is that for each RUN statement, a new container is launched from an intermediate image. An image is saved by the end of the command, but environment variables do not persist that way.

If you’re curious about an image, and would like to know if it provides default ENV variable values before the container is started, you can inspect images, and see which ENV entries are set by default:

```
# first, get the images on your system and their ids
$ docker images
# use one of those ids to take a closer look
$ docker inspect image-id

# look out for the "Env" entries

```


### Conclusion

By now, you should have a really good overview build-time arguments, environment variables, env_files and docker-compose templating with .env files. I hope you got a lot of value out of it, and can use the knowledge to save yourself lots of bugs in the future. You have to see them in action and apply them to your own work to truly make them part of your tool belt. The best way to make sure you will be able to make use of this information, is to learn by doing – go ahead and try some of those techniques