353

I have dockerfile

FROM centos:7
ENV foo=42

then I build it

docker build -t my_docker .

and run it.

docker run -it -d  my_docker

Is it possible to pass arguments from command line and use it with if else in Dockerfile? I mean something like

FROM centos:7
if (my_arg==42)
     {ENV=TRUE}
else:
     {ENV=FALSE}

and build with this argument.

 docker build -t my_docker . --my_arg=42
nick_gabpe
  • 5,113
  • 5
  • 29
  • 38
  • 2
    This should probably be handled from a build script. – Felix Glas Apr 27 '17 at 11:39
  • @Зелёный that is incorrect. See below answer, this can be accomplished with --build-arg – devnul3 Feb 07 '18 at 20:30
  • Accepted answer does not cover "if else condition" part of the question. Would be better to rename it to "Dockerfile with external arguments" if condition check didn't mean to be a requirement. – Ruslan Kabalin Jul 10 '18 at 13:43
  • @RuslanKabalin - the accepted answer has both "then" and "else" clauses. The only difference is *what* is tested in "if condition". For code shown in question: `RUN if [ "$arg" == "42" ]; then ENV=TRUE; else ENV=FALSE; fi`. Or if arg might be missing: `RUN if [ "x$arg" == "x42" ]; then ...` – ToolmakerSteve Apr 04 '19 at 11:06

15 Answers15

388

It might not look that clean but you can have your Dockerfile (conditional) as follow:

FROM centos:7
ARG arg
RUN if [[ -z "$arg" ]] ; then echo Argument not provided ; else echo Argument is $arg ; fi

and then build the image as:

docker build -t my_docker . --build-arg arg=45

or

docker build -t my_docker .

fstanis
  • 5,234
  • 1
  • 23
  • 42
Qasim Sarfraz
  • 5,822
  • 2
  • 20
  • 26
  • 30
    Shouldn't it be `[ "$arg" = "x" ]` instead of `[ "x$arg" = "x" ]` ? – Quannt Jun 07 '18 at 08:14
  • 7
    The ternary here is checking if any argument is provided, rather than checking for a specific argument. It would seem more obvious if rewritten as `if [ $arg != "" ] ;` but im sure there is some gotcha i'm not familiar with – myol Jun 27 '18 at 14:31
  • 43
    `if [[ -n "$arg" ]]` true if a param is not empty, `if [[ -z "$arg" ]]` true if a param is empty – acumartini Dec 14 '18 at 17:52
  • 11
    How to write a multiline if statement? – Ashutosh Chamoli Dec 17 '18 at 13:36
  • @AshutoshChamoli Can you please give an example of what are you trying to do? I have to keep the if statement singleline to use it within a RUN command. – Qasim Sarfraz Jan 04 '19 at 10:32
  • @QasimSarfraz Basically I am passing the environment variable with the docker build command. And in case someone tries to build without environment variable I am showing an error that environment variable not passed. So, basically the print statement is getting too long, and just for the sake of code readability, I want to split the statement in multi-line. – Ashutosh Chamoli Jan 07 '19 at 09:32
  • 1
    @AshutoshChamoli thanks for the explanation. You can just use shell way of splitting line e.g https://gist.github.com/MQasimSarfraz/30c8a1d48235d23b4f0a530444ed9ecd , you can just build on top of it and split further. – Qasim Sarfraz Jan 08 '19 at 19:07
  • 15
    @Quannt - no, see [Why do shell scripts ...](https://stackoverflow.com/q/174119/199364) `[ "x$arg" = "x" ]` looks like it is comparing two quoted strings, but the quotes get stripped; This keeps syntax correct. After quote-stripping: Good: `if x = x ..`. Bad: `if = `. HOWEVER, there ARE better ways to check for existence of a parameter: [Check existence of input arguments](https://stackoverflow.com/q/6482377/199364). – ToolmakerSteve Apr 04 '19 at 10:37
  • There's one caveat: Dockerfiles _must_ begin with a `FROM` statement. So if you need to build on a different base image, as I currently do, you cannot use this approach as you cannot run the `ARG` statement before the `FROM` statement. – Richard Dunn Nov 27 '19 at 15:01
  • 3
    @RichardDunn Not technically true, but also not really relevant here. ARG is a statement that can come before FROM for very specific purposes. See the [docs](https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact). You can use it to set the version of the base image. – Bastian Schiffthaler Dec 02 '19 at 18:58
  • 2
    Is it considered good practice to use this approach with Docker? – Harold L. Brown Nov 11 '20 at 09:08
  • 4
    Note that Debian based image requires `[`, `]` instead of `[[`, `]]` due to difference of default shell (in case when Alpine with `[[`, `]]`, it seems no problem). For detail, see [Answer: if statement - Is double square brackets \[\[ \]\] preferable over single square brackets \[ \] in Bash? - Stack Overflow](https://stackoverflow.com/a/669486/12721873) – Yukihiko Shinoda Apr 08 '21 at 12:03
  • @ToolmakerSteve: The version `[ "$arg" = "" ]` is fine, the `[` program gets 4 arguments, namely `$arg`, `=`, (empty string), `]`. And then it can figure this out. Without the quotes, it wouldn't work. With the `x` it would work without the quotes, so `[ x$arg = x ]` works as long as `$arg` doesn't contain any spaces. Then that latter would break. – Martin Ueding Nov 03 '21 at 18:52
  • @MartinUeding - 1) My main point was that Quannt had incorrectly suggested `[ "$arg" = "x" ]` - notice `x` is on one side, but not the other. 2) Understand that this is **ancient history** - the [FIRST link in my comment](https://stackoverflow.com/a/174288/199364) explains what the problem used to be: There used to be shells that "lost" the empty parameter after quote stripping. Hence the `x` `x` habit. I'm glad to hear this is no longer an issue. 3) And so anyone else reading this doesn't get confused: the answer has since been edited to use a different syntax. – ToolmakerSteve Nov 03 '21 at 19:53
  • 1
    Check out the other answer that uses stages in the Dockerfile. It doesn't need bash. – marcelocra Mar 17 '22 at 17:03
  • @Quannt how would you set a default value to $arg inside the then scope ? RUN if [[ -z "$arg" ]] ; then arg=1000 ; fi won't work... – eran otzap Jan 02 '23 at 08:51
250

There is an interesting alternative to the proposed solutions, that works with a single Dockerfile, require only a single call to docker build per conditional build and avoids bash.

Solution:

The following Dockerfile solves that problem. Copy-paste it and try it yourself.

ARG my_arg

FROM centos:7 AS base
RUN echo "do stuff with the centos image"

FROM base AS branch-version-1
RUN echo "this is the stage that sets VAR=TRUE"
ENV VAR=TRUE

FROM base AS branch-version-2
RUN echo "this is the stage that sets VAR=FALSE"
ENV VAR=FALSE

FROM branch-version-${my_arg} AS final
RUN echo "VAR is equal to ${VAR}"

Explanation of Dockerfile:

We first get a base image (centos:7 in your case) and put it into its own stage. The base stage should contain things that you want to do before the condition. After that, we have two more stages, representing the branches of our condition: branch-version-1 and branch-version-2. We build both of them. The final stage than chooses one of these stages, based on my_arg. Conditional Dockerfile. There you go.

Output when running:

(I abbreviated this a little...)

my_arg==2

docker build --build-arg my_arg=2 .
Step 1/12 : ARG my_arg
Step 2/12 : ARG ENV
Step 3/12 : FROM centos:7 AS base
Step 4/12 : RUN echo "do stuff with the centos image"
do stuff with the centos image
Step 5/12 : FROM base AS branch-version-1
Step 6/12 : RUN echo "this is the stage that sets VAR=TRUE"
this is the stage that sets VAR=TRUE
Step 7/12 : ENV VAR=TRUE
Step 8/12 : FROM base AS branch-version-2
Step 9/12 : RUN echo "this is the stage that sets VAR=FALSE"
this is the stage that sets VAR=FALSE
Step 10/12 : ENV VAR=FALSE
Step 11/12 : FROM branch-version-${my_arg}
Step 12/12 : RUN echo "VAR is equal to ${VAR}"
VAR is equal to FALSE

my_arg==1

docker build --build-arg my_arg=1 .
...
Step 11/12 : FROM branch-version-${my_arg}
Step 12/12 : RUN echo "VAR is equal to ${VAR}"
VAR is equal to TRUE

Thanks to Tõnis for this amazing idea!

User12547645
  • 6,955
  • 3
  • 38
  • 69
  • 14
    So far, the best approach. – Felipe Desiderati May 15 '20 at 18:57
  • Thought so too, thats why I posted it here. Spead the news @FelipeDesiderati – User12547645 May 16 '20 at 10:48
  • 2
    This is the best solution of all presented here, because you do not need to use workarounds with scripts/bash, but use a way that only involves Dockerfile knowledge. Great answer. – Akito May 28 '20 at 12:45
  • What does "ARG ENV" do? can you shed some light on this? Thanks. – Max Jul 05 '20 at 01:34
  • @Max thanks for pointing that out. It is not necessary – User12547645 Jul 06 '20 at 07:05
  • 18
    Interesting idea! The minus that I see with this approach for the general case is that both branches of the if statement get executed, which can be costly / have side effects. – Vitaliy Jul 08 '20 at 10:48
  • 17
    @Vitaliy Docker supports BuildKit in versions 18.09+ (for Linux-based containers), which will skip executing builds for unused stages. `DOCKER_BUILDKIT=1 docker build .` – rpatel Oct 01 '20 at 11:31
  • But I can't see that I can't copy based on my environment i.e. `COPY ./app /var/www/app`, only `dev` environment – jcarlosweb Mar 21 '21 at 21:51
  • I don't understand your comment @jcarlosweb. What is the issue? – User12547645 Mar 22 '21 at 08:57
  • 13
    Excelent solution, just remember to add ARG before the first FROM statement, since it is scoped. If you add it after the FROM statement, it won't be recognized in the branches FROM. Also, remember that ARGs are all scoped, if you define an ARG in a branch they won't be available in the final build - use ENV instead. – Tiago Duque Jun 10 '21 at 12:50
  • thats best solution ! – Ugur Kazdal Apr 27 '22 at 07:28
  • 1
    rpatel makes a good comment, but just to underscore it -- disabling BuildKit (i.e. `DOCKER_BUILDKIT=0 docker build`) will cause all branches to be executed (which will likely lead to unexpected behavior). – MandM Jul 08 '22 at 15:01
  • Best solution, I'm running docker v20 and found that the unreferenced build layer is NOT built. So it runs even faster than expected. – bmiller Sep 20 '22 at 18:51
  • It is indeed a very nice solution, but it becomes a problem when each version builds for 30 minutes (as an example). The Docker execution time will be significant since it will build all the versions first and only after that use 1 in the resulting image – red Feb 05 '23 at 13:19
  • Can this technique not also be applied to `COPY --from=` ? I get `failed to parse stage name "branch-version-${my_arg}": invalid reference format: repository name must be lowercase` – agirault May 18 '23 at 02:23
  • How could this handle multiple variables? I wish for some services to have maven but others just gradle maintaining a single dockerfile – gabriel garcia May 26 '23 at 08:38
92

Do not use build args described in other answers where at all possible. This is an old messy solution. Docker's target property solves for this issue.

Target Example

Dockerfile

FROM foo as base

RUN ...

# Build dev image
FROM base as image-dev

RUN ...
COPY ...

# Build prod image
FROM base as image-prod

RUN ...
COPY ...
docker build --target image-dev -t foo .
version: '3.4'

services:

  dev:
    build:
      context: .
      dockerfile: Dockerfile
      target: image-dev

Real World

Dockerfiles get complex in the real world. Use buildkit & COPY --from for faster, more maintainable Dockerfiles:

  • Docker builds every stage above the target, regardless of whether it is inherited or not. Use buildkit to build only inherited stages. Docker must by v19+. Hopefully this will be a default feature soon.
  • Targets may share build stages. Use COPY --from to simplify inheritance.
FROM foo as base
RUN ...
WORKDIR /opt/my-proj

FROM base as npm-ci-dev
# invalidate cache
COPY --chown=www-data:www-data ./package.json /opt/my-proj/package.json
COPY --chown=www-data:www-data ./package-lock.json /opt/my-proj/package-lock.json
RUN npm ci

FROM base as npm-ci-prod
# invalidate cache
COPY --chown=www-data:www-data ./package.json /opt/my-proj/package.json
COPY --chown=www-data:www-data ./package-lock.json /opt/my-proj/package-lock.json
RUN npm ci --only=prod

FROM base as proj-files
COPY --chown=www-data:www-data ./ /opt/my-proj

FROM base as image-dev
# Will mount, not copy in dev environment
RUN ...

FROM base as image-ci
COPY --from=npm-ci-dev /opt/my-proj .
COPY --from=proj-files /opt/my-proj .
RUN ...

FROM base as image-stage
COPY --from=npm-ci-prod /opt/my-proj .
COPY --from=proj-files /opt/my-proj .
RUN ...

FROM base as image-prod
COPY --from=npm-ci-prod /opt/my-proj .
COPY --from=proj-files /opt/my-proj .
RUN ...

Enable experimental mode.

sudo echo '{"experimental": true}' | sudo tee /etc/docker/daemon.json

Build with buildkit enabled. Buildkit builds without cache by default - enable with --build-arg BUILDKIT_INLINE_CACHE=1

CI build job.

DOCKER_BUILDKIT=1 \
    docker build \
    --build-arg BUILDKIT_INLINE_CACHE=1 \
    --target image-ci\
    -t foo:ci
    .

Use cache from a pulled image with --cache-from

Prod build job

docker pull foo:ci
docker pull foo:stage

DOCKER_BUILDKIT=1 \
    docker build \
    --cache-from foo:ci,foo:stage \
    --target image-prod \
    -t prod
    .
Dave
  • 1,356
  • 10
  • 15
  • 3
    Thanks! This helped a lot! The other answers focusses on using arguments to execute bash commands - this is the only answer that will allow you to execute docker commands if the "condition" is true (target is set to your environment) – Juan Venter Jul 08 '21 at 06:08
  • 4
    Some really useful ideas in here, many thanks! – opsb Aug 22 '21 at 08:28
  • 8
    This should be the accepted answer now. – Christian Fritz Apr 07 '22 at 17:53
  • I don't think this is the right answer. According to https://docs.docker.com/engine/reference/commandline/build/#specifying-target-build-stage---target the "target" flag is used for picking a stage in a multi-stages build scenario as the final stage. It's not used for the kind of if-else build in general. – David Ha Jun 05 '22 at 19:02
  • @DavidHa This details the above pattern in the same docs: https://docs.docker.com/develop/develop-images/multistage-build/ – Dave Jun 15 '22 at 05:33
  • @Dave you can certainly use that pattern for some special cases, like with a single break at one stage. But it is not as flexible enough as other solutions, for instance, If then B else C. – David Ha Jul 01 '22 at 01:57
  • 2
    With this pattern, I can have "USER " in normal container and "USER root" in -debug container, which is useful for me and easier achieved than with bash if/else approach. Thanks for this pattern! – Bogusław Kałka Jul 18 '22 at 13:00
32

From some reason most of the answers here didn't help me (maybe it's related to my FROM image in the Dockerfile)

So I preferred to create a bash script in my workspace combined with --build-arg in order to handle if statement while Docker build by checking if the argument is empty or not

Bash script:

#!/bin/bash -x

if test -z $1 ; then 
    echo "The arg is empty"
    ....do something....
else 
    echo "The arg is not empty: $1"
    ....do something else....
fi

Dockerfile:

FROM ...
....
ARG arg
COPY bash.sh /tmp/  
RUN chmod u+x /tmp/bash.sh && /tmp/bash.sh $arg
....

Docker Build:

docker build --pull -f "Dockerfile" -t $SERVICE_NAME --build-arg arg="yes" .

Remark: This will go to the else (false) in the bash script

docker build --pull -f "Dockerfile" -t $SERVICE_NAME .

Remark: This will go to the if (true)

Edit 1:

After several tries I have found the following article and this one which helped me to understand 2 things:

1) ARG before FROM is outside of the build

2) The default shell is /bin/sh which means that the if else is working a little bit different in the docker build. for example you need only one "=" instead of "==" to compare strings.

So you can do this inside the Dockerfile

ARG argname=false   #default argument when not provided in the --build-arg
RUN if [ "$argname" = "false" ] ; then echo 'false'; else echo 'true'; fi

and in the docker build:

docker build --pull -f "Dockerfile" --label "service_name=${SERVICE_NAME}" -t $SERVICE_NAME --build-arg argname=true .
dsaydon
  • 4,421
  • 6
  • 48
  • 52
27

The accepted answer may solve the question, but if you want multiline if conditions in the dockerfile, you can do that placing \ at the end of each line (similar to how you would do in a shell script) and ending each command with ;. You can even define someting like set -eux as the 1st command.

Example:

RUN set -eux; \
  if [ -f /path/to/file ]; then \
    mv /path/to/file /dest; \
  fi; \
  if [ -d /path/to/dir ]; then \
    mv /path/to/dir /dest; \
  fi

In your case:

FROM centos:7
ARG arg
RUN if [ -z "$arg" ] ; then \
    echo Argument not provided; \
  else \
    echo Argument is $arg; \
  fi

Then build with:

docker build -t my_docker . --build-arg arg=42
Lucas Basquerotto
  • 7,260
  • 2
  • 47
  • 61
26

Just use the "test" binary directly to do this. You also should use the noop command ":" if you don't want to specify an "else" condition, so docker does not stop with a non zero return value error.

RUN test -z "$YOURVAR" || echo "var is set" && echo "var is not set"
RUN test -z "$YOURVAR" && echo "var is not set" || :
RUN test -z "$YOURVAR" || echo "var is set" && :
benjhess
  • 277
  • 3
  • 2
  • 2
    Same as `RUN [ -z "$YOURVAR" ] && ... || :`, I believe – OneCricketeer Apr 17 '18 at 14:52
  • 4
    For the following statement, if the var is set then both the echo are executed. `RUN test -z "$YOURVAR" || echo "var is set" && echo "var is not set"` – Harshad Vyawahare May 13 '20 at 10:38
  • 1
    Indeed. Remember those are not branched conditional blocks, they execute serially, put `&&` in front of `||`: `test ! -z "$YOURVAR" && echo "var is set" || echo "var is not set"` – Brandt May 19 '20 at 07:47
19

According to the doc for the docker build command, there is a parameter called --build-arg.

Example usage:

docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 .

IMO it's what you need :)

Pang
  • 9,564
  • 146
  • 81
  • 122
barat
  • 1,040
  • 8
  • 14
10

Exactly as others told, shell script would help.

Just an additional case, IMHO it's worth mentioning (for someone else who stumble upon here, looking for an easier case), that is Environment replacement.

Environment variables (declared with the ENV statement) can also be used in certain instructions as variables to be interpreted by the Dockerfile.

The ${variable_name} syntax also supports a few of the standard bash modifiers as specified below:

  • ${variable:-word} indicates that if variable is set then the result will be that value. If variable is not set then word will be the result.

  • ${variable:+word} indicates that if variable is set then word will be the result, otherwise the result is the empty string.

Community
  • 1
  • 1
Jing Li
  • 14,547
  • 7
  • 57
  • 69
6

Using Bash script and Alpine/Centos

Dockerfile

FROM alpine  #just change this to centos 

ARG MYARG=""
ENV E_MYARG=$MYARG

ADD . /tmp
RUN chmod +x /tmp/script.sh && /tmp/script.sh

script.sh

#!/usr/bin/env sh

if [ -z "$E_MYARG" ]; then
    echo "NO PARAM PASSED"
else
    echo $E_MYARG
fi

Passing arg: docker build -t test --build-arg MYARG="this is a test" .

....
Step 5/5 : RUN chmod +x /tmp/script.sh && /tmp/script.sh
 ---> Running in 10b0e07e33fc
this is a test
Removing intermediate container 10b0e07e33fc
 ---> f6f085ffb284
Successfully built f6f085ffb284

Without arg: docker build -t test .

....
Step 5/5 : RUN chmod +x /tmp/script.sh && /tmp/script.sh
 ---> Running in b89210b0cac0
NO PARAM PASSED
Removing intermediate container b89210b0cac0
....
Muhammad Soliman
  • 21,644
  • 6
  • 109
  • 75
1

I saw a lot of possible solutions, but no one fits on the problem I faced today. So, I'm taking time to answer the question with one another possible solution that worked to me.

In my case I toke advantage of the well known if [ "$VAR" == "this" ]; then echo "do that"; fi. The caveat is that Docker, I don't know explain why, doesn't like the double equal on this case. So we need to write like that if [ "$VAR" = "this" ]; then echo "do that"; fi.

There is the full example that worked in my case:

FROM node:16

# Let's set args and envs
ARG APP_ENV="dev"
ARG NPM_CMD="install"
ARG USER="nodeuser"
ARG PORT=8080
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
ENV PATH=$PATH:/home/node/.npm-global/bin
ENV NODE_ENV=${APP_ENV}

# Let's set the starting point
WORKDIR /app

# Let's build a cache
COPY package*.json .
RUN date \
 # If the environment is production or staging, omit dev packages
 # If any other environment, install dev packages
 && if [ "$APP_ENV" = "production" ]; then NPM_CMD="ci --omit=dev"; fi \
 && if [ "$APP_ENV" = "staging" ]; then NPM_CMD="ci --omit=dev"; fi \
 && npm ${NPM_CMD} \
 && usermod -d /app -l ${USER} node

# Let's add the App
COPY . .

# Let's expose the App port
EXPOSE ${PORT}

# Let's set the user
USER ${USER}

# Let's set the start App command
CMD [ "node", "server.js" ]

So if the user pass the proper build argument, the docker build command will create an image of app for production. If not, it will create an image of the app with dev Node.js packages.

To make it works, you can call like this:

# docker build --build-arg APP_ENV=production -t app-node .
Charles Santos
  • 739
  • 9
  • 12
1

For any one trying to build Windows based image, you need to access argument with %% for cmd.

# Dockerfile Windows
# ...
ARG SAMPLE_ARG
RUN if %SAMPLE_ARG% == hello_world ( `
    echo hehe %SAMPLE_ARG% `
    ) else ( `
    echo haha %SAMPLE_ARG% `
)
# ...

BTW, ARG declaration must be placed after FROM, otherwise the argument will not be available.

Summer Sun
  • 947
  • 13
  • 33
1

# The ARGs in front of FROM is for image
ARG IMLABEL=xxxx \
    IMVERS=x.x

FROM ${IMLABEL}:${IMVERS}

# The ARGs after FROM is for parameters to be used in the script
ARG  condition-x

RUN if [ "$condition-x" = "condition-1" ]; then \
      echo "$condition-1"; \
    elif [ "$condition-x" = "condition-1" ]; then \
      echo "$condition-2"; \
    else
      echo "$condition-others"; \
    fi

build -t --build-arg IMLABEL --build-arg IMVERS --build-arg condition-x -f Dockerfile -t image:version .
Eric Chen
  • 47
  • 1
  • 5
0

I had a similar issue for setting proxy server on a container.

The solution I'm using is an entrypoint script, and another script for environment variables configuration. Using RUN, you assure the configuration script runs on build, and ENTRYPOINT when you run the container.

--build-arg is used on command line to set proxy user and password.

As I need the same environment variables on container startup, I used a file to "persist" it from build to run.

The entrypoint script looks like:

#!/bin/bash
# Load the script of environment variables
. /root/configproxy.sh
# Run the main container command
exec "$@"

configproxy.sh

#!/bin/bash

function start_config {
read u p < /root/proxy_credentials

export HTTP_PROXY=http://$u:$p@proxy.com:8080
export HTTPS_PROXY=https://$u:$p@proxy.com:8080

/bin/cat <<EOF > /etc/apt/apt.conf 
Acquire::http::proxy "http://$u:$p@proxy.com:8080";
Acquire::https::proxy "https://$u:$p@proxy.com:8080";
EOF
}

if [ -s "/root/proxy_credentials" ]
then
start_config
fi

And in the Dockerfile, configure:

# Base Image
FROM ubuntu:18.04

ARG user
ARG pass

USER root

# -z the length of STRING is zero
# [] are an alias for test command
# if $user is not empty, write credentials file
RUN if [ ! -z "$user" ]; then echo "${user} ${pass}">/root/proxy_credentials ; fi

#copy bash scripts
COPY configproxy.sh /root
COPY startup.sh .

RUN ["/bin/bash", "-c", ". /root/configproxy.sh"]

# Install dependencies and tools
#RUN apt-get update -y && \
#    apt-get install -yqq --no-install-recommends \
#    vim iputils-ping

ENTRYPOINT ["./startup.sh"]
CMD ["sh", "-c", "bash"]

Build without proxy settings

docker build -t img01 -f Dockerfile . 

Build with proxy settings

docker build -t img01 --build-arg user=<USER> --build-arg pass=<PASS> -f Dockerfile . 

Take a look here.

Siegfried
  • 90
  • 1
  • 7
0

You can just add a simple check:

RUN [ -z "$ARG" ] \
    && echo "ARG argument not provided." \
    && exit 1 || exit 0
Patrick José Pereira
  • 1,613
  • 2
  • 11
  • 12
0

I ended up with writing my own framework for Dockerfile generation based on a python-like syntax.

It's open source now, you can try it here: https://github.com/gkpln3/sand

You can write your Sandfile like this:

# Sandfile
from sand import *

From("ubuntu", Tag="20.04")
Run([
    "apt-get update",
    "apt-get install ffmpeg python3"
])

# Install python debugger on debug images.
if config.DEBUG:
    Run("pip3 install pdb")

Copy("app", "/app")
Entrypoint("python3 /app/app.py")

And it will be converted to this

# Auto-generated by Sand, do not edit!
FROM ubuntu:20.04
RUN apt-get update
RUN apt-get install ffmpeg python3
RUN pip3 install pdb
COPY app /app
ENTRYPOINT python3 /app/app.py

You can pass the configuration values using the -D or --set flag.

$ sand config -DDEBUG=True

Or use a YAML file.

# sand.yaml
DEBUG: True
$ sand config --values sand.yaml
gkpln3
  • 1,317
  • 10
  • 24