Passing multiple parameters to docker container

Viewed 1815

I'm trying to pass 2 parameters to a docker container for a dash app (via a shell script). Passing one parameter works, but two doesn't. Here's what happens when I pass two parameters:

command:

sudo sh create_dashboard.sh 6 4

Error:

creating docker
Running for parameter_1: 6 
Running for parameter_2: 4 
usage: app.py [-h] [-g parameter_1] [-v parameter_2]
app.py: error: argument -g/--parameter_1: expected one argument

The shell script:

echo "creating docker"
docker build -t dash-example .
echo "Running for parameter_1: $1 "
echo "Running for parameter_2: $2 "
docker run --rm -it -p 8080:8080 --memory=10g dash-example $1 $2

Dockerfile:

FROM python:3.8

WORKDIR /app
COPY src/requirements.txt ./
RUN pip install -r requirements.txt
COPY src /app
EXPOSE 8080
ENTRYPOINT [ "python", "app.py", "-g", "-v"]

When I use this command:

sudo sh create_dashboard.sh 6

the docker container runs perfectly, with parameter_2 being None.

2 Answers

You can pass a command into the shell of a container like this:

docker run --rm -it -p 8080:8080 dash-example sh -c "--memory=10g dash-example $1 $2"

So it allows arguments and any other command.

When you docker run ... dash-example $1 $2, the additional parameters are interpreted as the "command" the container should run. Since your image has an ENTRYPOINT, the words of the command are just tacked on to the end of the words of the entrypoint (see Understand how CMD and ENTRYPOINT interact in the Dockerfile documentation). There's no way to cause the words of one command to be interspersed with the words of another; you are effectively getting a command line of

python app.py -g -v 6 4

The approach I'd recommend here is to not use an ENTRYPOINT at all. Make sure you can directly run the application script (its first line should be #!/usr/bin/env python3, it should be executable) and make the image's default CMD be to run the script:

FROM python:3.9
...
# RUN chmod +x app.py  # if needed
# no ENTRYPOINT at all
CMD ["./app.py"]       # finds "python" via the shebang line

Then your wrapper can supply a complete command line, including the options you need to run:

#!/bin/sh
docker run --rm -it -p 8080:8080 --memory=10g dash-example \
  ./app.py -g "$1" -v "$2"

(There is an alternate "container as command" pattern, where the ENTRYPOINT contains the command to run and the CMD its options. This can lead to awkward docker run --entrypoint command lines for routine debugging tasks, and if the command itself is short it doesn't really save you a lot. You'd still need to repeat the -g and -v options in the wrapper.)

Related