skip to Main Content

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

2

Answers


  1. 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.

    Login or Signup to reply.
  2. 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
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search