How do I use Docker environment variable in ENTRYPOINT array?

DockerDockerfile

Docker Problem Overview


If I set an environment variable, say ENV ADDRESSEE=world, and I want to use it in the entry point script concatenated into a fixed string like:

ENTRYPOINT ["./greeting", "--message", "Hello, world!"]

with world being the value of the environment varible, how do I do it? I tried using "Hello, $ADDRESSEE" but that doesn't seem to work, as it takes the $ADDRESSEE literally.

Docker Solutions


Solution 1 - Docker

You're using the exec form of ENTRYPOINT. Unlike the shell form, the exec form does not invoke a command shell. This means that normal shell processing does not happen. For example, ENTRYPOINT [ "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: ENTRYPOINT [ "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.(from Dockerfile reference)

In your case, I would use shell form

ENTRYPOINT ./greeting --message "Hello, $ADDRESSEE\!"

Solution 2 - Docker

After much pain, and great assistance from @vitr et al above, i decided to try

  • standard bash substitution
  • shell form of ENTRYPOINT (great tip from above)

and that worked.

ENV LISTEN_PORT=""

ENTRYPOINT java -cp "app:app/lib/*" hello.Application --server.port=${LISTEN_PORT:-80}

e.g.

docker run --rm -p 8080:8080 -d --env LISTEN_PORT=8080 my-image

and

docker run --rm -p 8080:80 -d my-image

both set the port correctly in my container

Refs

see https://www.cyberciti.biz/tips/bash-shell-parameter-substitution-2.html

Solution 3 - Docker

I tried to resolve with the suggested answer and still ran into some issues...

This was a solution to my problem:

ARG APP_EXE="AppName.exe"
ENV _EXE=${APP_EXE}

# Build a shell script because the ENTRYPOINT command doesn't like using ENV
RUN echo "#!/bin/bash \n mono ${_EXE}" > ./entrypoint.sh
RUN chmod +x ./entrypoint.sh

# Run the generated shell script.
ENTRYPOINT ["./entrypoint.sh"]

Specifically targeting your problem:

RUN echo "#!/bin/bash \n ./greeting --message ${ADDRESSEE}" > ./entrypoint.sh
RUN chmod +x ./entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]

Solution 4 - Docker

For me, I wanted to store the name of the script in a variable and still use the exec form.

Note: Make sure, the variable you are trying to use is declared an environment variable either from the commandline or via the ENV directive.

Initially I did something like:

ENTRYPOINT [ "${BASE_FOLDER}/scripts/entrypoint.sh" ]

But obviously this didn't work because we are using the shell form and the first program listed needs to be an executable on the PATH. So to fix this, this is what I ended up doing:

ENTRYPOINT [ "/bin/bash", "-c", "exec ${BASE_FOLDER}/scripts/entrypoint.sh \"${@}\"", "--" ]

Note the double quotes are required

What this does is to allow us to take whatever extra args were passed to /bin/bash, and supply those same arguments to our script after the name has been resolved by bash.


man 7 bash

> --
A -- signals the end of options and disables further option processing. Any arguments after the -- are treated as filenames and arguments. An argument of - is equivalent to --.

Solution 5 - Docker

I SOLVED THIS VERY SIMPLY!

> IMPORTANT: The variable which you wish to use in the ENTRYPOINT MUST be ENV type (and not ARG type).

EXAMPLE #1:

ARG APP_NAME=app.jar                    # $APP_NAME can be ARG or ENV type.
ENV APP_PATH=app-directory/$APP_NAME    # $APP_PATH must be ENV type.
ENTRYPOINT java -jar $APP_PATH

> This will result with executing: java -jar app-directory/app.jar

EXAMPLE #2 (YOUR QUESTION):

ARG ADDRESSEE="world"                       # $ADDRESSEE can be ARG or ENV type.
ENV MESSAGE="Hello, $ADDRESSEE!"            # $MESSAGE must be ENV type.
ENTRYPOINT ./greeting --message $MESSAGE

> This will result with executing: ./greeting --message Hello, world!

  • Please verify to be sure, whether you need quotation-marks "" when assigning string variables.

> MY TIP: Use ENV instead of ARG whenever possible to avoid confusion on your part or the SHELL side.

Solution 6 - Docker

In my case worked this way: (for Spring boot app in docker)

ENTRYPOINT java -DidMachine=${IDMACHINE} -jar my-app-name

and passing the params on docker run

docker run --env IDMACHINE=Idmachine -p 8383:8383 my-app-name

Solution 7 - Docker

Here is what worked for me:

ENTRYPOINT [ "/bin/bash", "-c", "source ~/.bashrc && ./entrypoint.sh ${@}", "--" ]

Now you can supply whatever arguments to the docker run command and still read all environment variables.

Solution 8 - Docker

I solved the problem using a variation on "create a custom script" approach above. Like this:

FROM hairyhenderson/figlet
ENV GREETING="Hello"
RUN printf '#!/bin/sh\nfiglet -W \${GREETING} \$@\n' > /runme && chmod +x /runme
ENTRYPOINT ["/runme"]
CMD ["World"]

Run like

docker container run -it --rm -e GREETING="G'Day" dockerfornovices/figlet-greeter Alec

Solution 9 - Docker

If someone wants to pass an ARG or ENV variable to exec form of ENTRYPOINT then a temp file created during image building process might be used.

In my case I had to start the app differently depending on whether the .NET app has been published as self-contained or not. What I did is I created the temp file and I used its name in the if statement of my bash script.

Part of my dockerfile:

ARG SELF_CONTAINED=true #ENV SELF_CONTAINED=true also works
# File has to be used as a variable as it's impossible to pass variable do ENTRYPOINT using Exec form. File name allows to check whether app is self-contained
RUN touch ${SELF_CONTAINED}.txt
COPY run-dotnet-app.sh .
ENTRYPOINT ["./run-dotnet-app.sh", "MyApp" ]

run-dotnet-app.sh:

#!/bin/sh

FILENAME=$1

if [ -f "true.txt" ]; then
   ./"${FILENAME}"
else
   dotnet "${FILENAME}".dll
fi

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPsycho PunchView Question on Stackoverflow
Solution 1 - DockervitrView Answer on Stackoverflow
Solution 2 - Dockermlo55View Answer on Stackoverflow
Solution 3 - DockerBen KauffmanView Answer on Stackoverflow
Solution 4 - Dockersmac89View Answer on Stackoverflow
Solution 5 - DockerTal Jacob - Sir JacquesView Answer on Stackoverflow
Solution 6 - DockerScorebyView Answer on Stackoverflow
Solution 7 - DockerPavel TankovView Answer on Stackoverflow
Solution 8 - DockerAlec the GeekView Answer on Stackoverflow
Solution 9 - DockerŁukasz SypniewskiView Answer on Stackoverflow