In my Dockerfile on Ubuntu 16.04 with docker 17.12.1-ce I use
ARG ver=latest
ARG pkg=master
For building a docker container, I would like to call docker build --build-arg ver=v1 . in order to set a special package.
The code-handling part in my Dockerfile is
RUN if[ "x$ver" = "xv1" ] ; then pkg=v1.2.3 ; fi
RUN echo $pkg
Unfortunately, the ARG pkg variable is not updated and the echo statement always shows its initial value.
What can I do, to update my build variable pkg inside an if statement??
You will not be able to pass variables from one RUN to another because each RUN command is executed in a different shell.
A solution to your problem would be to extract the logic into a script and execute docker with the build arguments something like this:
if [ $ver="v1" ]; then pkg=1.2.3; fi; docker build --build-arg ver=$ver --build-arg pkg=$pkg .
Related
Docker build tricky behavior:
Dockerfile
ARG php_version="7.2"
ARG flavor="stretch"
FROM php:${php_version}-fpm-${flavor}
#ARG php_version="7.2"
ENV php_v $php_version
CMD echo $php_v
If you build it and run:
docker build -t args:1.0 .
docker run -it --name testargs args:1.0
Output is empty string instead of the expected "7.2"
But if the third ARG line is uncommented we get "7.2"
Why does it behave this way?
Each FROM in a Dockerfile represents a new build stage and an ARG declared before the FROM is not available for use in the newer build stages starting with another FROM.
To quote the relevant section of the doc:
An ARG declared before a FROM is outside of a build stage, so it can’t
be used in any instruction after a FROM.
The problem is i cannot get the docker build arg value in the shell script while running the docker build.
My docker build command:
DOCKER_BUILDKIT=1 docker build --no-cache --progress=plain \
-t test \
--build-arg WHL_PATH=/fake/path \
.
Dockerfile
ARG WHL_PATH
FROM python:3.8.8
COPY test.sh .
RUN ./test.sh $WHL_PATH
and in the test.sh the "$1" is empty...., if in the Dockerfile i put some constant value then i will be able to see that value in the $1, but with docker build arg or set the build arg as ENV VAR are always empty...
Where am i doing wrong, how should i achieve this?
Docker version 20.10.5, build 55c4c88
Build args are scoped. Before the first FROM step they only apply to the FROM steps to adjust the image you use. Within each stage, an ARG step applies to the remaining steps within that stage. So the fix is to reorder your steps:
FROM python:3.8.8
COPY test.sh .
ARG WHL_PATH
RUN ./test.sh $WHL_PATH
Oops, i never realised the position of the ARG instruction matters, basically:
any ARG before the first FROM can be used in any FROM line
any ARG within a build stage (after a FROM) can be used in that build stage
After i moved the ARG WHL_PATH after the line FROM xxx it works perfectly, hope this can save some of your time in the future.
And i was inspired by this answer actually: https://stackoverflow.com/a/50292255/7658313
I currently have two Dockerfiles that are identical except for some ENV vars at the beginning that have different values. I want to combine them into one Dockerfile and select the ENV vars depending on one build-arg / ARG instead.
I tried something like this with $target being either WIN or UNIX:
FROM alpine
ARG target
ARG VAR1_WIN=Value4Win
ARG VAR1_UNIX=Value4Unix
ARG VAR1=VAR1_$target
ARG VAR1=${!VAR1}
RUN echo $VAR1
But it throws an error: failed to process "${!VAR1}": missing ':' in substitution
I tried a lot but I'm unable to double expand $VAR1.
How do I do this correctly? Thx.
For the conditional syntax, there is a pattern you can use with a multi-stage build:
# ARG defined before the first FROM can be used in FROM lines
ARG target
# first base image for WIN target
FROM alpine as base-WIN
# switching to ENV since ARG doesn't pass through to the next stage
ENV VAR1=Value4Win
# second base image for UNIX target
FROM alpine as base-UNIX
ENV VAR1=Value4Unix
# select one of the above images based on the value of target
FROM base-${target} as release
RUN echo $VAR1
The double expand syntax ${!VAR} only works in bash, while Dockerfile is not parsed by shell. According to the docker manual, Dockerfile does not support double expand.
Note that alpine use ash instead of bash, so it does not support ${!VAR} either. You have to use eval + echo. Try RUN VAR1="$(eval "echo \$$VAR1")"; echo $VAR1.
If you can't pass Value4Win or Value4Unix directly via --build-arg, here is one way:
FROM alpine
ARG target
ARG VAR1=Value4${target}
RUN echo $VAR1
Doing a docker build --build-arg target=WIN . gives:
Step 4/4 : RUN echo $VAR1
---> Running in 6e94bc28d459
Value4WIN
I use Docker Toolbox for windows (for compatibility issues) and in the Dockerfile I specify an ARG so that I can use it when building the image with --build-arg command. Inside the dockerfile I also have some COPY commands and there I would like to use my variable but when I run docker build --build-arg VERSION_APP=something . it does not translate the variable . I have already used $VERSION_APP or ${VERSION_APP} or %VERSION_APP%.
FROM alpine
MAINTAINER Marinos
ARG VERSION_APP
RUN apk update && apk add dos2unix
COPY script.sh /home/script.sh
RUN chmod a+x /home/script.sh
RUN dos2unix /home/script.sh
RUN sh /home/script.sh
COPY installation.txt /home/Desktop/${VERSION_APP}
UPDATE
It seems that you should pass the whole path to the variable you use that is how I got it working.
If you actually use the command below then it is expected not to work because the argument called VERSION_APP
docker build --build-arg myVar=something
So the command should be
docker build --build-arg VERSION_APP=something
And in Dockerfile it should be %VERSION_APP% also you may need to use ENV like below:
ARG VERSION_APP
ENV VERSION_APP ${VERSION_APP}
I have a strange behavior with my Dockerfile. I try to make it write file with text coming from environment varibales :
FROM ubuntu:14.04
ENV KEY ''
ENV VAL ''
RUN echo "${KEY}:${VAL}" > /etc/test
CMD []
I built this image and run it like this :
docker run -it --rm -e KEY=aaa -e VAL=bbb mytest
If I display the /etc/test file, it is empty (it is present, but empty). It seems that when it creates the file, environment variables are not set.
Any idea?
Thank you
The command in the docker file RUN echo "${KEY}:${VAL}" > /etc/test is executed when you build the image using docker build ...
Thus this is logical, since at that point the env variables are empty.
You need to move the commad to the CMD command which will run when the image is started.
You can define KEY and VALUE as arguments and set their values when you're building the docker image.
FROM ubuntu:14.04
ARG KEY
ARG VAL
RUN echo "${KEY}:${VAL}" > /etc/test
CMD []
Then you can build the image using like this:
docker build --build-arg KEY=<value> --build-arg VAL=<value> .
https://docs.docker.com/engine/reference/builder/#using-arg-variables