I'm using ENTRYPOINT
to pass in an argument when running docker run
but I cannot get the runtime argument to surface in my script as an argument.
Dockerfile
FROM debian:latest
ENV a="my arg in Dockerfile"
COPY . .
RUN chmod x myscript.sh
ENTRYPOINT ["/bin/bash", "-c", "/myscript.sh ${a}"]
with myscript.sh
#!/bin/bash
echo "From script: $@"
When I run docker build -t my_image .
then docker run -it --rm my_image
I get the result as expected: From script: my arg in Dockerfile
But when I run docker run -it --rm my_image from_run
I get the same result: From script: my arg in Dockerfile
so the "from_run" is not being passed down to the script through ENTRYPOINT
.
I read that arguments passed after the image name is appended to the ENTRYPOINT
but clearly I'm not understanding something here.
Same result when using the exec form as opposed to JSON form:
ENTRYPOINT /myscript.sh ${a}
https://docs.docker.com/engine/reference/run/#entrypoint-default-command-to-execute-at-runtime
CodePudding user response:
Bash is Bash, see bash manual how -c
pases arguments. The following:
/bin/bash -c "/myscript.sh ${a}" from_run
passes only one argument to myscript.sh and that is unquoted $a
, so $a
undergoes word splitting and filename expansion. And the argument from_run
is assigned to $0
. I would do:
ENTRYPOINT ["/bin/bash", "-c", "./myscript.sh \"$a\" \"$@\"", "--"]
Note that it's typical to use upper case (and unique names) for environment variables $a
.
CodePudding user response:
The main container command is made up of two parts. The string you pass after the docker run image-name
replaces the Dockerfile CMD
, and it's appended to the Dockerfile ENTRYPOINT
.
For your docker run
command to work, you need to provide the command you want to run as ENTRYPOINT
and its arguments as CMD
. You do not need an environment variable here. However, it is important that both parts use JSON-array syntax and that neither invokes a shell. If ENTRYPOINT
includes a shell then things get syntactically complex (see @KamilCuk's answer); if CMD
includes a shell then it won't get invoked but the command will be invoked with /bin/sh
and -c
as parameters instead.
FROM debian:latest
COPY myscript.sh /usr/local/bin/myscript # preserves execute permissions
ENTRYPOINT ["myscript"] # in a $PATH directory
CMD ["my", "arg", "in", "Dockerfile"]
docker run --rm the-image
docker run --rm the-image my arg from command line
If you want the initial set of command-line arguments to be included and the docker run
arguments to be appended, you can move them into the ENTRYPOINT
line; note that the docker run --entrypoint
is syntactically awkward if you ever do decide you need to remove some of the options.
ENTRYPOINT ["myscript", "--first-default", "--second-default"]
# CMD []
docker run --rm the-image
docker run --rm the-image --user-option
docker run --entrypoint myscript the-image --first-default --no-second-default
If you can update your application to accept options as environment variables in addition to command-line settings, this makes all of this syntactically easier.
ENV FIRST_DEFAULT=yes
ENV SECOND_DEFAULT=yes
CMD ["myscript"]
docker run --rm the-image
docker run --rm -e USER_OPTION=yes the-image
docker run --rm -e SECOND_DEFAULT=no the-image