How to pass arguments to Shell Script through docker run

BashShellDockerCommand Line-Arguments

Bash Problem Overview


I am new to the docker world. I have to invoke a shell script that takes command line arguments through a docker container. Ex: My shell script looks like:

#!bin/bash
echo $1

Dockerfile looks like this:

FROM ubuntu:14.04
COPY ./file.sh /
CMD /bin/bash file.sh

I am not sure how to pass the arguments while running the container

Bash Solutions


Solution 1 - Bash

with this script in file.sh

#!/bin/bash
echo Your container args are: "$@"

and this Dockerfile

FROM ubuntu:14.04
COPY ./file.sh /
ENTRYPOINT ["/file.sh"]

you should be able to:

% docker build -t test .
% docker run test hello world
Your container args are: hello world

Solution 2 - Bash

Use the same file.sh

#!/bin/bash
echo $1

Build the image using the existing Dockerfile:

docker build -t test .

Run the image with arguments abc or xyz or something else.

docker run -ti --rm test /file.sh abc

docker run -ti --rm test /file.sh xyz

Solution 3 - Bash

With Docker, the proper way to pass this sort of information is through environment variables.

So with the same Dockerfile, change the script to

#!/bin/bash
echo $FOO

After building, use the following docker command:

docker run -e FOO="hello world!" test

Solution 4 - Bash

There are a few things interacting here:

  1. docker run your_image arg1 arg2 will replace the value of CMD with arg1 arg2. That's a full replacement of the CMD, not appending more values to it. This is why you often see docker run some_image /bin/bash to run a bash shell in the container.

  2. When you have both an ENTRYPOINT and a CMD value defined, docker starts the container by concatenating the two and running that concatenated command. So if you define your entrypoint to be file.sh, you can now run the container with additional args that will be passed as args to file.sh.

  3. Entrypoints and Commands in docker have two syntaxes, a string syntax that will launch a shell, and a json syntax that will perform an exec. The shell is useful to handle things like IO redirection, chaining multiple commands together (with things like &&), variable substitution, etc. However, that shell gets in the way with signal handling (if you've ever seen a 10 second delay to stop a container, this is often the cause) and with concatenating an entrypoint and command together. If you define your entrypoint as a string, it would run /bin/sh -c "file.sh", which alone is fine. But if you have a command defined as a string too, you'll see something like /bin/sh -c "file.sh" /bin/sh -c "arg1 arg2" as the command being launched inside your container, not so good. See the table here for more on how these two options interact

  4. The shell -c option only takes a single argument. Everything after that would get passed as $1, $2, etc, to that single argument, but not into an embedded shell script unless you explicitly passed the args. I.e. /bin/sh -c "file.sh $1 $2" "arg1" "arg2" would work, but /bin/sh -c "file.sh" "arg1" "arg2" would not since file.sh would be called with no args.

Putting that all together, the common design is:

FROM ubuntu:14.04
COPY ./file.sh /
RUN chmod 755 /file.sh
# Note the json syntax on this next line is strict, double quotes, and any syntax
# error will result in a shell being used to run the line.
ENTRYPOINT ["file.sh"]

And you then run that with:

docker run your_image arg1 arg2

There's a fair bit more detail on this at:

Solution 5 - Bash

What I have is a script file that actually runs things. This scrip file might be relatively complicated. Let's call it "run_container". This script takes arguments from the command line:

run_container p1 p2 p3

A simple run_container might be:

#!/bin/bash
echo "argc = ${#*}"
echo "argv = ${*}"

What I want to do is, after "dockering" this I would like to be able to startup this container with the parameters on the docker command line like this:

docker run image_name p1 p2 p3

and have the run_container script be run with p1 p2 p3 as the parameters.

This is my solution:

Dockerfile:

FROM docker.io/ubuntu
ADD run_container /
ENTRYPOINT ["/bin/bash", "-c", "/run_container \"$@\"", "--"]

Solution 6 - Bash

If you want to run it @build time :

CMD /bin/bash /file.sh arg1

if you want to run it @run time :

ENTRYPOINT ["/bin/bash"]
CMD ["/file.sh", "arg1"]

Then in the host shell

docker build -t test .
docker run -i -t test

Solution 7 - Bash

Another option...

To make this works

docker run -d --rm $IMG_NAME "bash:command1&&command2&&command3"

in dockerfile

ENTRYPOINT ["/entrypoint.sh"]

in entrypoint.sh

#!/bin/sh

entrypoint_params=$1
printf "==>[entrypoint.sh] %s\n" "entry_point_param is $entrypoint_params"

PARAM1=$(echo $entrypoint_params | cut -d':' -f1) # output is 1 must be 'bash' it     will be tested    
PARAM2=$(echo $entrypoint_params | cut -d':' -f2) # the real command separated by     &&

printf "==>[entrypoint.sh] %s\n" "PARAM1=$PARAM1"
printf "==>[entrypoint.sh] %s\n" "PARAM2=$PARAM2"

if [ "$PARAM1" = "bash" ];
then
    printf "==>[entrypoint.sh] %s\n" "about to running $PARAM2 command"
    echo $PARAM2 | tr '&&' '\n' | while read cmd; do
        $cmd
    done    
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
QuestionAkash MehtaView Question on Stackoverflow
Solution 1 - BashPartly CloudyView Answer on Stackoverflow
Solution 2 - BashBMWView Answer on Stackoverflow
Solution 3 - BashMichaelView Answer on Stackoverflow
Solution 4 - BashBMitchView Answer on Stackoverflow
Solution 5 - BashjkhView Answer on Stackoverflow
Solution 6 - BashGilles QuenotView Answer on Stackoverflow
Solution 7 - BashwagnermarquesView Answer on Stackoverflow