DOCKER ASSIGN a shell value to ENV in DOCKERFILE - docker

I'm drastically looking for the solution of passing the value to the ENV variable in DOCKERFILE.
EX:
FROM alphine
COPY domainname.txt .
ENV NAME=$(cat /domainname.txt)

If you insist to get NAME value when docker build, you could use next:
Dockerfile:
FROM alpine
ARG NAME
ENV NAME=${NAME}
domainname.txt:
hello
Execution:
$ docker build --build-arg NAME=$(cat ./domainname.txt) -t abc:1 . --no-cache
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM alpine
---> d4ff818577bc
Step 2/3 : ARG NAME
---> Running in f1c58e816499
Removing intermediate container f1c58e816499
---> dc4d5894440b
Step 3/3 : ENV NAME=${NAME}
---> Running in 9b8f98a3857c
Removing intermediate container 9b8f98a3857c
---> 2b0c68ddc994
Successfully built 2b0c68ddc994
Successfully tagged abc:1
$ docker run --rm -it abc:1 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=2155d7368c3e
TERM=xterm
NAME=hello
HOME=/root
You could see above NAME be assigned as hello.
Simple explanation:
NAME=$(cat ./domainname.txt) assign the hello to NAME
--build-arg pass the hello to docker build's ARG NAME
ENV NAME=${NAME} get the hello from ARG NAME

Related

Detecting username in Dockerfile

I need to run a cmd that will create my home folder within a docker container. So, if my username in my linux box is josecz then I could use it from within a Dockerfile to run a cmd like:
RUN mkdir /home/${GetMyUsername}
and get the folder /home/josecz after the Dockerfile is processed.
The only way just as commented by folks: use ARG, next gives you a workable minimal example:
Dockerfile:
FROM alpine:3.14.0
ARG GetMyUsername
RUN echo ${GetMyUsername}
RUN mkdir -p /home/${GetMyUsername}
Execution:
cake#cake:~/3$ docker build --build-arg GetMyUsername=`whoami` -t abc:1 . --no-cache
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM alpine:3.14.0
---> d4ff818577bc
Step 2/4 : ARG GetMyUsername
---> Running in 4d87a0970dbd
Removing intermediate container 4d87a0970dbd
---> 8b67912b3788
Step 3/4 : RUN echo ${GetMyUsername}
---> Running in 2d68a7e93715
cake
Removing intermediate container 2d68a7e93715
---> 100428a1c526
Step 4/4 : RUN mkdir -p /home/${GetMyUsername}
---> Running in 938d10336daa
Removing intermediate container 938d10336daa
---> 939729b76f09
Successfully built 939729b76f09
Successfully tagged abc:1
Explaination:
When docker build, you could use whoami to get the username who run the docker build, then pass to args GetMyUsername. Then, in Dockerfile, you could use ${GetMyUsername} to get the value.

Building a Linux Docker image on Windows 10: "exec format error"

I am using as a base, the following image: https://github.com/Kaggle/docker-python/blob/main/Dockerfile.
Here is my Dockerfile:
FROM kaggle/python
RUN ["chmod", "+x", "/opt/conda/etc/profile.d/conda.sh"]
SHELL ["/bin/bash", "--login", "-c" ]
RUN ["/opt/conda/etc/profile.d/conda.sh"]
ENTRYPOINT [ "/usr/bin/env" ]
RUN ["exec '$#'"]
RUN ["bash"]
I am running the command: docker build -t kaggle/no-jupyter .
At line 4 I get the error:
> [3/7] RUN ["/opt/conda/etc/profile.d/conda.sh"]:
#6 0.263 standard_init_linux.go:228: exec user process caused: exec format error
Here is a link to the conda.sh file: https://pastebin.com/Epu4d7Nq
I read that this might be because I am building a Linux image on Windows10...Any ideas?
See RUN Syntax:
RUN
RUN has 2 forms:
RUN (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows)
RUN ["executable", "param1", "param2"] (exec form)
What you choose is exec form which won't run in a shell, so your /opt/conda/etc/profile.d/conda.sh surely fails.
To fix it you need to change to:
RUN ["bash", "/opt/conda/etc/profile.d/conda.sh"]
Or just use shell form:
RUN /opt/conda/etc/profile.d/conda.sh
Minimal example:
run.sh:
echo "hello"
Dockerfile:
FROM ubuntu:16.04
COPY run.sh /
RUN ["bash", "/run.sh"]
Execution:
$ docker build -t abc:1 . --no-cache
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM ubuntu:16.04
---> 065cf14a189c
Step 2/3 : COPY run.sh /
---> 8741ec438afd
Step 3/3 : RUN ["bash", "/run.sh"]
---> Running in 5e6754c79bc1
hello
Removing intermediate container 5e6754c79bc1
---> 3edd77959de4
Successfully built 3edd77959de4
Successfully tagged abc:1
AND, if not use bash, it will show error likes next:
Dockerfile:
FROM ubuntu:16.04
COPY run.sh /
RUN ["/run.sh"]
Execution:
$ docker build -t abc:1 . --no-cache
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM ubuntu:16.04
---> 065cf14a189c
Step 2/3 : COPY run.sh /
---> 82412a703847
Step 3/3 : RUN ["/run.sh"]
---> Running in 2a2b00f966c7
standard_init_linux.go:211: exec user process caused "exec format error"
The command '/run.sh' returned a non-zero code: 1

docker multistage build fails with multiple --build-arg

I am using this Dockerfile
ARG IMAGE_ONE
FROM ${IMAGE_ONE}
RUN cat /etc/debian_version
ARG IMAGE_TWO
FROM ${IMAGE_TWO}
RUN cat /etc/debian_version
But it fails because it does not use the second var IMAGE_TWO:
$ docker build --no-cache --build-arg IMAGE_ONE=debian:7 --build-arg IMAGE_TWO=debian:8 .
Sending build context to Docker daemon 2.048kB
Step 1/6 : ARG IMAGE_ONE
Step 2/6 : FROM ${IMAGE_ONE}
---> 90c038768099
Step 3/6 : RUN cat /etc/debian_version
---> Running in f842d9cf4f17
7.11
Removing intermediate container f842d9cf4f17
---> 0f7f7afdd8a6
Step 4/6 : ARG IMAGE_TWO
---> Running in ed3d36f2f9cb
Removing intermediate container ed3d36f2f9cb
---> ae4ae3cabc02
Step 5/6 : FROM ${IMAGE_TWO}
--->
Step 6/6 : RUN cat /etc/debian_version
---> Running in 6f1c165e2765
OCI runtime create failed: container_linux.go:296:
starting container process caused "exec: \"/bin/sh\":
stat /bin/sh: no such file or directory": unknown
Docker version:
$ docker --version
Docker version 17.12.0-ce, build c97c6d6
Is there something wrong in my Dockerfile or is the docker build command wrong?
The reason is because IMAGE_TWO is not in the same scope check this
https://docs.docker.com/engine/reference/builder/#scope
Basically the ARG IMAGE_TWO is still part of the first stage and goes out of scope when that stage ends and will not be part of the second stage.
Declaring the arguments at the beginning allow the IMAGE_TWO to be in the second stage.
ARG IMAGE_ONE
ARG IMAGE_TWO
FROM ${IMAGE_ONE}
RUN cat /etc/debian_version
FROM ${IMAGE_TWO}
RUN cat /etc/debian_version
docker build --build-arg=IMAGE_ONE=debian:7 --build-arg=IMAGE_TWO=debian:8 .

dockerfile: get environment variable from host

I'm familiar with ARG, which allows for arguments to be passed into a dockerfile, like so:
Dockerfile
FROM ubuntu:latest
ARG foo
RUN echo $foo
$ docker build --build-arg foo=foo .
Sending build context to Docker daemon 2.048 kB
Step 1/3 : FROM ubuntu:latest
---> 00fd29ccc6f1
Step 2/3 : ARG foo
---> Running in 8f6ddda3254d
---> 9c658744762b
Removing intermediate container 8f6ddda3254d
Step 3/3 : RUN echo $foo
---> Running in 37bcbf3c5052
foo
---> 0e162e793204
Removing intermediate container 37bcbf3c5052
Successfully built 0e162e793204
However, what I want is to forward an environment variable from the host into the Dockerfile, without the need for the user to specify the --build-arg. So, for example, I want them to be able to execute this:
$ export foo=foo
$ docker build .
And get the same result.
Is this possible?
The easiest way to do this is to use docker-compose to build, with a docker-compose file like the following:
my-awesome-service:
build:
context: .
dockerfile: Dockerfile
args:
- FOO=${FOO}
Then your user can run docker-compose build and the FOO variable will be forwarded into the Dockerfile. See: https://docs.docker.com/compose/compose-file/#args

How to pass ARG value to ENTRYPOINT?

Docker 1.9 allows to pass arguments to a dockerfile. See link: https://docs.docker.com/engine/reference/builder/#arg
How can i pass the same arugments within ENTRYPOINT Instruction??
My dockerfile has
ARG $Version=3.1
ENTRYPOINT /tmp/folder-$Version/sample.sh start
I am getting an error while creating container with above dockerfile.
Please suggest what is the correct way to specify the argument within ENTRYPOINT instruction??
Like Blake Mitchell sais, you cannot use ARG in ENTRYPOINT. However you can use your ARG as a value for ENV, that way you can use it with ENTRYPOINT:
Dockerfile
ARG my_arg
ENV my_env_var=$my_arg
ENTRYPOINT echo $my_env_var
and run:
docker build --build-arg "my_arg=foo" ...
Short answer: you need to use ENV
Both ARG and ENV are not expanded in ENTRYPOINT or CMD. (https://docs.docker.com/engine/reference/builder/#environment-replacement) However, because ENVs are passed in as part of the environment, they are available at run time, so the shell can expand them. (This means you can't use the array form of ENTRYPOINT or CMD.)
Here is an example:
$ cat arg/Dockerfile
FROM debian:jessie
ARG FOO=bar
ENTRYPOINT echo ${FOO:-foo}
$ sudo docker build arg
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM debian:jessie
---> f50f9524513f
Step 2 : ARG FOO=bar
---> Using cache
---> 2cfdcb514b62
Step 3 : ENTRYPOINT echo ${FOO:-foo}
---> Running in 21fb9b42c10d
---> 75e5018bad83
Removing intermediate container 21fb9b42c10d
Successfully built 75e5018bad83
$ sudo docker run 75e5018bad83
foo
$ sudo docker run -e FOO=bas 75e5018bad83
bas
$ sudo docker build --build-arg FOO=bas arg
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM debian:jessie
---> f50f9524513f
Step 2 : ARG FOO=bar
---> Using cache
---> 2cfdcb514b62
Step 3 : ENTRYPOINT echo ${FOO:-foo}
---> Using cache
---> 75e5018bad83
Successfully built 75e5018bad83
$ sudo docker run 75e5018bad83
foo
$ cat env/Dockerfile
FROM debian:jessie
ARG FOO=bar
ENV FOO=${FOO}
ENTRYPOINT echo ${FOO:-foo}
$ sudo docker build env
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM debian:jessie
---> f50f9524513f
Step 2 : ARG FOO=bar
---> Using cache
---> 2cfdcb514b62
Step 3 : ENV FOO ${FOO}
---> Running in f157a07c1b3e
---> a5e8c5b65a17
Removing intermediate container f157a07c1b3e
Step 4 : ENTRYPOINT echo ${FOO:-foo}
---> Running in 66e9800ef403
---> 249fe326e9ce
Removing intermediate container 66e9800ef403
Successfully built 249fe326e9ce
$ sudo docker run 249fe326e9ce
bar
$ sudo docker run -e FOO=bas 249fe326e9ce
bas
$ sudo docker build --build-arg FOO=bas env
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM debian:jessie
---> f50f9524513f
Step 2 : ARG FOO=bar
---> Using cache
---> 2cfdcb514b62
Step 3 : ENV FOO ${FOO}
---> Running in 6baf31684b9f
---> 8f77ad154798
Removing intermediate container 6baf31684b9f
Step 4 : ENTRYPOINT echo ${FOO:-foo}
---> Running in 892ac47cabed
---> fa97da85bf8a
Removing intermediate container 892ac47cabed
Successfully built fa97da85bf8a
$ sudo docker run fa97da85bf8a
bas
$
Just in case you have more than one parameter to pass to ENTRYPOINT or CMD, you can do like that:
FROM openjdk:8-jdk-alpine
ARG PROFILE
ENV PROFILE=${PROFILE}
...
CMD java -jar -Dspring.profiles.active=$(echo ${PROFILE}) /app/server.jar
I'm struggling with this for a day, thanks for #Rotareti for mentioning. It needs to be in ENV before it can be used to the ENTRYPOINT.
ENV variable=$from_ARG_variable
ENTRYPOINT exec your_exec_sh_file $variable
Hope this helps.
The syntax for ARG should omit the $.
Instead of ARG $Version=3.1, try ARG Version=3.1.

Resources