Different methods to add condition in Dockerfile
In this article, we will be learning about various methods to add conditions in Dockerfile.
When we create a Docker image, the best practice is to not hardcode any value in the dockerfile and it has to be passed dynamically to the docker build command while building the image.
Also, while creating the docker container, it is best to pass or set the Environment variable so that the container as a whole or the application within the docker container can access it.
This is made possible, by using the two variables inside the dockerfile namely, ARG
and ENV
.
Let us take a look at the scenarios, where these variables can fit in appropriately:
- Variable ARG: This variable can be used while building the docker image. This means that the variable is accessible only while creating the docker image and NOT accessible for the docker container.
- Variable ENV: This variable can be used by the container and it has the default value and it can be overwritten while creating the containers.
Let us understand how to use these variables with an example:
Case 1:
FROM ubuntu
ARG VER1=v10.0.0
ENV VER2=v20.0.0
RUN echo $VER1
RUN echo $VER2
Build the docker by passing an argument and notice that our container uses the ENV version from input argument while takes ARG version from the Dockerfile. So this confirms that ENV variable can be overwritten using input build argument but ARG value can not be overwritten.
Output:
docker build --build-arg VER1=v2.1.0 --build-arg VER2=v10.0.0 .
Method 1: Docker file if else
Suppose that you have a build system and you have to install Grunt or Gulp. So you have the dockerfile which has installation instructions for both. However, you don't want to install both of them and you have to decide on the package based on the condition. So, what would be the way to do it inside dockerfile?
So, there are two ways to do this. Let's check them out.
Option 1:
Add the condition in the RUN command as shown below:
RUN if grep -q "gulp" package.json; then echo succeed; fi
Option 2:
Use the shell script. Below is the sample code to do this:
if [ "${BUILD_TOOL}" = "GRUNT" ]; then echo "GRUNT setup"; echo "Done GRUNT setup"; elif [ "${BUILD_TOOL}" = "GULP" ]; then echo "GULP setup"; echo "Done GULP setup"; fi
Copy the above shell script inside the dockerfile and run the below command which builds the image based on the argument specified.
FROM centos:centos7
ARG BUILD_TOOL
COPY setup.sh /setup.sh
RUN ./setup.sh
RUN rm /setup.sh
Command:
docker build --build-arg BUILD_TOOL=GULP . (or GRUNT)
Now, let us touch upon various other methods in detail that can help us implement the conditions in the dockerfile.
The below example takes the arguments while creating the docker image.
The if-else condition is written inside the dockerfile and the arguments are passed while building the docker image.
Method 2: Docker file if else with arg conditions
Below is the dockerfile which takes the argument and checks if the argument is passed or not and runs appropriately depending on the condition specified.
Dockerfile:
FROM centos:7
ARG argument
RUN \
if [[ -z "${argument}" ]] ; \
then echo ***Argument is not provided*** ; \
else \
echo ***Argument is ${argument}*** ; \
fi
Output:
Below is the output when the above-mentioned dockerfile is run by passing the arguments
docker build -t test_image -build-arg argument=100 .
Step 1/3 : FROM centos:7
---> eeb6ee3f44bd
Step 2/3 : ARG argument
---> Using cache
---> ffedfa347c83
Step 3/3 : RUN if [[ -z "${argument}" ]] ; then echo ***Argument is not provided*** ; else echo ***Argument is ${argument}*** ; fi
---> Running in 5ef5b781c633
***Argument is 100***
Removing intermediate container 5ef5b781c633
---> 269bacbed525
Successfully built 269bacbed525
Successfully tagged test_image:latest
In the above screenshot, you can notice that when the docker was built by passing the argument, the code inside the “else” condition got executed and printed in the console.
Now, let us build the dockerfile without passing the argument using the below command
Output:
docker build -t test_image .
Step 1/3 : FROM centos:7
---> eeb6ee3f44bd
Step 2/3 : ARG argument
---> Using cache
---> ffedfa347c83
Step 3/3 : RUN if [[ -z "${argument}" ]] ; then echo ***Argument is not provided*** ; else echo ***Argument is ${argument}*** ; fi
---> Using cache
---> a65d38e0c929
Successfully built a65d38e0c929
Successfully tagged test_image:latest
In the above screenshot, you can notice that when docker was built without passing the argument, the code inside the “if” condition got executed.
Method 3: Test input arguments in Docker fil
In this method, let us write a shell script which checks if the argument is passed or not using the “test” command.
Further, lets us copy this shell script in the dockerfile and build it.
Shell script:
#!/bin/bash -x if test -z $1 ; then echo "The argument is empty" else echo "The argument is not empty: $1" fi
Dockerfile:
FROM centos:7
ARG argument
COPY script.sh /home/script.sh
RUN chmod u+x /home/script.sh && /home/script.sh $argument
Output:
Build the docker by passing the argument and check the results!!
docker build -t bash_image:1.0 –build-arg argument=80 .
In the above screenshot, you can notice that when the docker was built by passing the argument, the code inside the “else” condition got executed and printed in the console.
Build the docker without passing the argument and see that the else condition got executed in this case.
Output:
docker build -t bash_image:1.0 .
In the above screenshot, you can notice that when docker was built without passing the argument, the code inside the “if” condition got executed.
Method 4: Using ENV and ARG variable
Let us now use the ENV variable along with the ARG variable in the dockerfile.
Notice that the values passed as an environment will always persist.
Shell script:
#!/usr/bin/env sh if [ -z "$env_argument" ]; then echo "No Parameters passed..." else echo "Parameter passed..." $env_argument fi
Dockerfile:
FROM centos:7
ARG argument=""
ENV env_argument=$argument
COPY test_script.sh /home
RUN chmod +x /home/test_script.sh && /home/test_script.sh
In the below screenshot, you can notice that when the docker was built by passing the argument, the code inside the “else” condition got executed and printed in the console.
Output:
docker build -t test —build-arg argument=”Hello,How are you” .
In the below screenshot, you can notice that when docker was built without passing the argument, the code inside the “if” condition got executed.
Output:
docker build -t test .
One important thing to note is whenever we use the conditional logic in the dockerfile, it is essential to build the dockerfile each time as we use the build-arg and it won't be cached.
Due to this, adding conditional logic in dockerfile slows down the build process.
Method 5: Conditional Dockerfile without bash
Here is one more alternative which uses a single dockerfile and avoids bash. Let's take a look!
Dockerfile:
ARG argument
ARG ENV
FROM centos:7 AS base
RUN echo "using centos as base image"
FROM base AS branch-version-1
RUN echo "seting VAR=TRUE"
ENV VAR=TRUE
FROM base AS branch-version-2
RUN echo "setting VAR=FALSE"
ENV VAR=FALSE
FROM branch-version-${argument} AS final
RUN echo "Varibale is equal to ${VAR}"
In this case we will pass input argument as 1 in which case the VAR value must be set as TRUE
based on our conditions.
Output:
docker build -t multiline:1.0 --build-arg argument=1 .
In this case we will pass input argument as 2 in which case the VAR value must be set as FALSE
based on our conditions.
Output:
docker build -t multiline:1.0 --build-arg argument=2 .
Conclusion
In this article, we have learnt about adding conditions in Dockerfile. I hope this article makes it clear to you and I suggest everyone try it out yourself.
In case you have any doubts, please feel free to add your questions in the comment section below and I shall try to respond at the earliest.
Happy learning!!
References
https://stackoverflow.com/questions/43654656/dockerfile-if-else-condition-with-external-arguments
https://docs.docker.com/build/building/multi-stage/
https://stackoverflow.com/questions/37057468/conditional-env-in-dockerfile