How to verify build args is set properly in Dockerfile - docker

I've got the following line in Dockerfile:
ARG COOL_ID
...
ENTRYPOINT ["java", "-jar", "/usr/share/java/${COOL_ID}/app.jar"]
but when I run it there's an error:
Error: Unable to access jarfile /usr/share/java//app.jar
and I can see that my ${COOL_ID} argument was not formatted correctly.
How can I fix it?

It will not substitute the variable, as Docker treat ENTRYPOINT and CMD as a command so processing variables like shell will not work. Try to change the CMD to run it as a shell and then you will able to process variable the same as the shell.
Also, you can not use ARG in CMD to treat them as an environment variable, you just use them inside Dockerfile, to use them as an environment variable you must assign them to some ENV.
ARG COOL_ID
ENV COOL_ID=$COOL_ID
I will also suggest to verify and check COOL_ID in Docker build time, if not set then it should print the warning or error to the user, see below example if ARG not passed to builds params then it will print an error message to the user.
ARG COOL_ID
#see ARG is for build time
RUN if [ -z $COOL_ID ];then \
>&2 echo "\n****************Warning!!!!*************\n"; \
>&2 echo "COOL_ID seems empty!" ;\
fi
ENV COOL_ID=$COOL_ID
# ENV is for run time
CMD ["sh", "-c", "java -jar /usr/share/java/${COOL_ID}/app.jar"]
Now build the docker with --build-arg
docker build --build-arg COOL_ID=myid -t myjava .
If you missed passing COOL_ID you will be notified.

Related

How do I make Timeout command from entrypoint in Dockerfile

I have been trying to run timeout command on my shellscript with time being passed as variabe through Dockerfile
This is my DokcerFile(sample)
FROM locustio/locust:1.2.3
ARG TIME_CHECK=15
COPY --chown=locust:locust ping.sh .
RUN echo "Hello $TIME_CHECK"
RUN chown locust:locust /home/locust && chmod +x ./ping.sh
ENTRYPOINT ["/bin/bash","-c", "timeout $TIME_CHECK ./ping.sh"]
Docker build happens successfully with below command and I can the value being passed correctly
docker build -t pingit --build-arg TIME_CHECK=10
When I do docker run it fails with following error
Try 'timeout --help' for more information.
I do understand this is because ENTRYPOINT is not recogninsing variable as such.
What am I doing wrong can you anyone help me here.
From docker reference, you can only access ARG values at build-time.
To pass a value to the runtime environment variable, you can use ENV instruction:
FROM locustio/locust:1.2.3
ARG TIME_CHECK=15
# assign ENV from ARG
ENV TIME_CHECK=${TIME_CHECK}
COPY --chown=locust:locust ping.sh .
RUN echo "Hello $TIME_CHECK"
RUN chown locust:locust /home/locust && chmod +x ./ping.sh
ENTRYPOINT ["/bin/bash","-c", "timeout $TIME_CHECK ./ping.sh"]
Just add a ENV TIME_CHECK=$TIME_CHECK to your dockerfile after the ARG statement.
The issue is that ARG is at build time. If you need to use it as environment variable then you need to set the variable yourself

Pass ARGs in docker ENTRYPOINT

I'm running my app on Azure App Services, so I don't have access to docker run command. Now, I want to pass some variables into ENTRYPOINT for which I'm trying to use ARGs during build time itself. Here is how it looks,
docker build -t $IMAGE_NAME --build-arg env=dev --build-arg amplify_key=xxxxxxxxxxxxxx .
In my Dockerfile,
ARG env
ARG amplify_key
ENTRYPOINT ["/bin/bash", "-c", "init.sh $env $amplify_key"]
But this doesn't seem to be working. Please let me know the issue.
$variable references can be either expanded in the Dockerfile or by the shell when a command gets run. Only some Dockerfile commands perform variable expansions; for RUN, CMD, and ENTRYPOINT, it is only done by a shell. When a shell does the expansion it's not aware of Docker-specific ARGs, only environment variables, so you need to copy the argument to an ENV. There's an example of this in the Dockerfile documentation.
ARG env
ARG amplify_key
ENV env=$env amplify_key=$amplify_key
CMD init.sh $env $amplify_key
Assuming init.sh is your own script, though, once you have those values in environment variables, you can just access them directly, without passing them through positional parameters.
#!/bin/sh
echo "Running in $env environment"
curl -H "Authorization: Bearer $amplify_key" ...
ARG env
ARG amplify_key
ENV env=$env amplify_key=$amplify_key
CMD ["init.sh"]
This lets you do things like override the variable values at startup time more easily, and if you need to manually supply parameters to the command, the set of mandatory options is much smaller. If you're using the pattern of ENTRYPOINT doing some first-time setup and then running exec "$#" to run the CMD, this also works much better (ENTRYPOINT and sh -c have some tricky interactions).

Dockerfile: pass argument to RUN npm run build

I have a dockerfile with these lines:
ARG ENVIRONMENT
ENV ENVIRONMENT $ENVIRONMENT
RUN npm run ng build --configuration=${ENVIRONMENT}
I cant get the "RUN npm run ng build --configuration= to pass the value of $ENVIRONMENT to the npm command.
What is the syntax for this?
Per the Dockerfile ARG docs,
The ARG instruction defines a variable that users can pass at build-time to the builder with the docker build command using the --build-arg = flag.
in order to accept an argument as part of the build, we use --build-arg.
Dockerfile ENV docs:
The ENV instruction sets the environment variable to the value .
We also need to include an ENV statement because the CMD will be executed after the build is complete, and the ARG will not be available.
FROM busybox
ARG ENVIRONMENT
ENV ENVIRONMENT $ENVIRONMENT
CMD echo $ENVIRONMENT
will cause an environment variable to be set in the image, so that it is available during a docker run command.
docker build -t test --build-arg ENVIRONMENT=awesome_environment .
docker run -it test
This will echo awesome_environment.
Try changing your RUN command do this:
RUN npm run ng build --configuration=$ENVIRONMENT
This should work. Check here
Thanks.

How to pass arguments to a bash file in the docker ENTRYPOINT?

I've a dockerfile where I use a custom entrypoint.sh. In this file I want to use the ARGS which I pass from docker-compose to the dockerfile.
The problem is that I don't get the content of the variable to the dockerfile I just get the variable name.
For example:
ARGS ENVIROMENT=production
ENTRYPOINT ["/var/www/html/entrypoint.sh"]
CMD ["${ENVIROMENT}"]
entrypoint.sh
#!/bin/sh
cd /var/www/html
composer update
echo $1;
The echo $1 show "${Enviroment}" instead of "production" what I expect.
Ouch ! You've hit a sensible point of Docker with this question.
But first, let me clarify some point here :
First of all, you have a typo in your example. It's ARG not ARGS
ARG allows you to define a build-time variable. Meaning that this variable will only be usefull when doing a docker image build command. You'll then be able to override it with --build-arg. For example :
docker image build --build-arg ENVIROMENT=integration ...`
At the opposite, ENV allows you to define an environment variable which can be used during runtime.
You can find all the info you need in the official documentation for env and arg
Now, back to the point...
To make it simple:
Do not use both ENTRYPOINT and CMD when you want to pass some environment variable to your entrypoint from your cmd. It's just a pain. Really.
When you want to use a environment variable inside CMD, then you'll have to either use bash format, or to prefix the command with sh -c for exec format :
CMD ["sh", "-c", "echo ${GREETINGS}"]
#or
CMD echo ${GREETINGS}
Here is a Dockerfile that works with both syntax (just uncomment the CMD you want to use) :
FROM debian:8
ENV GREETINGS="hello world"
#CMD ["sh", "-c", "echo ${GREETINGS}"]
#CMD echo ${GREETINGS}
You can find more detailled info on those issues :
Issue 5509
Issue 34772
I would like to complete Marc abouchacra's answer.
What is still missing is how to use the ARG command.
A possible solution could be:
ARG ENVIRONMENT=production
ENV ENVIRONMENT=$ENVIRONMENT
CMD exec /var/www/html/entrypoint.sh $ENVIRONMENT
The exec is there to make sure your entrypoint.sh is the process with the PID=1.

Docker ENV in CMD

I am trying to do the following:
Pass a build arg to my docker build command
Store that as an env variable in my container
Use it in my CMD to start when my container launches.
Below is my setup:
FROM ubuntu:xenial
ARG EXECUTABLE
ENV EXECUTABLE ${EXECUTABLE}
CMD ["/opt/foo/bin/${EXECUTABLE}", "-bar"]
Here is how i'm building container
docker build --build-arg EXECUTABLE=$EXECUTABLE -t test_image .
Here is how i'm running image
docker run -d test_image
When I run the container it crashes and tells me
docker: Error response from daemon: OCI runtime create failed:
container_linux.go:296: starting container process caused
"exec: \"/opt/foo/bin/${EXECUTABLE}\": stat /opt/foo/bin/${EXECUTABLE}:
no such file or directory": unknown.
To use environment variables, you need to use shell.
https://docs.docker.com/engine/reference/builder/#cmd
Note: Unlike the shell form, the exec form does not invoke a command
shell. This means that normal shell processing does not happen. For
example, CMD [ "echo", "$HOME" ] will not do variable substitution on
$HOME. If you want shell processing then either use the shell form or
execute a shell directly, for example: CMD [ "sh", "-c", "echo $HOME"
]. When using the exec form and executing a shell directly, as in the
case for the shell form, it is the shell that is doing the environment
variable expansion, not docker.
Based on this, I think you can work fine by the following Dockerfile.
FROM ubuntu:xenial
ARG EXECUTABLE
ENV EXECUTABLE ${EXECUTABLE}
CMD [ "sh", "-c", "/opt/foo/bin/${EXECUTABLE}", "-bar"]
You'll have to write out an executable or shim as ARG / ENV substitution is not supported for CMD.
The list of supported substitutions:
ADD
COPY
ENV
EXPOSE
FROM
LABEL
STOPSIGNAL
USER
VOLUME
WORKDIR
as well as:
ONBUILD (when combined with one of the supported instructions above)
A workaround is to write your executable to a file and execute that:
FROM ubuntu:xenial
ARG EXECUTABLE
RUN : \
&& /bin/echo -e "#!/bin/sh\nexec '/bin/$EXECUTABLE' -bar" > /exe \
&& chmod +x /exe
CMD ["/exe"]
Build:
docker build -t test --build-arg EXECUTABLE=echo .
Run:
$ docker run -ti test
-bar
Another way to access the environment variable passed is by running it as:
docker run -e EXECUTABLE=<some_value> <docker_image>
Then, in the dockerfile
CMD exec /opt/foo/bin/${EXECUTABLE} -bar

Resources