Pass in Arguments when Doing a Docker Run - docker

If I have the following Dockfile
FROM centos:8
RUN yum update -y
RUN yum install -y python38-pip
COPY . /app
WORKDIR /app
RUN pip3 install -r requirements.txt
ENTRYPOINT ["python3"]
CMD ["app.py"]
With app being the following:
#!/usr/bin/python
import sys
print('Here is your param: ', sys.argv[0])
When I call docker run -it (myimg), how can I pass in a parameter so the output would be the param?
ex:
docker run -it (myparam) "testfoo"
would print
Here is your param: testfoo

sys.argv[0] refer to the FileName so you can not expect testfoo when you run docker run -it my_image testfoo
The first item in the list, sys.argv[0], is the name of the Python script. The rest of the list elements, sys.argv[1] to sys.argv[n], are the command line arguments 2 through n
print('Here is your param: file Name', sys.argv[0],'args testfoo:',sys.argv[1])
So you can just replace the entrypoint to below then you are good to pass runtime argument testfoo
ENTRYPOINT ["python3","app.py"]
Now pass argument testfoo
docker run -it --rm my_image testfoo

Anything you provide after the image name in the docker run command line replaces the CMD from the Dockerfile, and then that gets appended to the ENTRYPOINT to form a complete command.
Since you put the script name in CMD, you need to repeat that in the docker run invocation:
docker run -it myimg app.py testfoo
(This split of ENTRYPOINT and CMD seems odd to me. I'd make sure the script starts with a line like #!/usr/bin/env python3 and is executable, so you can directly run ./app.py; make that be the CMD and remove the ENTRYPOINT entirely.)

Related

Dockerfile does not run executable

I have the following Dockerfile
FROM rikorose/gcc-cmake
RUN git clone https://github.com/hect1995/UBIMET_Challenge.git
WORKDIR /UBIMET_Challenge
RUN mkdir build
WORKDIR build
#RUN apt-get update && apt-get -y install cmake=3.13.1-1ubuntu3 protobuf-compiler
RUN cmake ..
RUN make
CMD ["./ubimet /UBIMET_Challenge/data/1706221600.29 output.csv"]
Even though it says it executes the last line when building it does not (or it does it incorrectly) as if you run last line it should generate 2 files that are not being generated once I check them using:
docker run -t -i trial /bin/bash
Nevertheless, if I get inside the container and from there I run:
./ubimet /UBIMET_Challenge/data/1706221600.29 output.csv
It generates the files, so why does it not generate the files while building?
CMD is the default command to run when you start your container. You are overriding
this by passing /bin/bash to docker run.
Either change CMD to RUN (to run your script at build time) or run docker run without the trailing command (to run when you start the container).
You are using CMD wrong. CMD has 3 forms, none of which are what you are using:
CMD
The CMD instruction has three forms:
CMD ["executable","param1","param2"] (exec form, this is the preferred form)
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
CMD command param1 param2 (shell form)
You can use CMD like this:
CMD ["./ubimet", "/UBIMET_Challenge/data/1706221600.29", "output.csv"]

Shebang in JavaScript ignored when executed as command in Docker with "/bin/bash" as entrypoint

When I try to execute a JavaScript file with a shebang such as #!/usr/bin/env node through the command argument of docker run ... it seems to "ignore" the shebang.
$ docker run --rm foobar/hello-world /hello-world.js
/hello-world.js: line 2: syntax error near unexpected token `'Hello, World!''
/hello-world.js: line 2: `console.log('Hello, World!');'
Dockerfile
FROM node:13.12-alpine
COPY hello-world.js /hello-world.js
RUN chmod +x /hello-world.js
RUN apk update && apk update && apk add bash
ENTRYPOINT ["/bin/bash"]
hello-world.js
#!/usr/bin/env node
console.log('Hello, World!');
When I use /hello-world.js as the entrypoint directly (ENTRYPOINT ["/hello-world.js"]) it works correctly.
Add -c to the entrypoint so bash will expect a command. Without -c it interprets its argument as the name of a bash script to execute.
ENTRYPOINT ["/bin/bash", "-c"]
I'd recommend just setting the default CMD to the program you're installing in your container, and generally preferring CMD to ENTRYPOINT if you only need one of them.
FROM node:13.12-alpine
COPY hello-world.js /hello-world.js
RUN chmod +x /hello-world.js
CMD ["/hello-world.js"]
When you provide a command at the docker run command line, it overrides the Dockerfile CMD (if any), and it's appended to the ENTRYPOINT. In your original example the ENTRYPOINT from the Dockerfile is combined with the docker run command and you're getting a combined command bash /hello-world.js.
If you do need an interactive shell to debug the container, you can launch that with
docker run --rm -it foobar/hello-world /bin/sh

Dockerfile accept multiple args and choose an action

I have a python image that launches a web app and I'm wondering if it's possible to run pytest from container - I would like to choose if I want to run the app or run the tests.
Is possible?
My dockerfile looks like:
FROM python:3.7-slim-buster
COPY ./ ./x
WORKDIR ./x
RUN pip install -r requirements.txt
EXPOSE 5000
CMD ["gunicorn", "-b", "0.0.0.0:5000", "--log-level=info", "app:app"]
Is possible to run something like docker run x --someargumenttolaunchtests?
You can set an ARGS value in your dockerfile which is an argument that you provided during build time. If you want to provide an arguement in run time, you can set an environment variable via docker run -e some_environment.
Then, you can, with a bash script, choose what you want to run. So your bash script provides your if some_eivonrment = ? then etc. You would have to make this bash script prior to run time and either COPY it to your dockerfile or bind it on run time.
So here is an example of a bash script.
#!bin/bash
ENVIRONMENT=$(export some_environment)
if("$ENVIRONMENT" = "test") ; then
python run_test.py
else
python main.py
fi
Before I forget, you need to set the permissions for this bash script.
So in your dockerfile:
COPY ./bash_script.sh /app
WORKDIR /app
RUN chmod u+x bash_script.sh
You can completely override the entrypoint script and avoid gunicorn. Use something like:
docker run --rm -it --entrypoint bash myimagename pytest

What's the meaning of "CMD [ "-?" ]" in Docker?

《The Docker Book v17.12.0-ce》 Page 223
Listing 6.19: Our war fle fetcher
FROM ubuntu:16.04
MAINTAINER James Turnbull
ENV REFRESHED_AT 2016-06-01
RUN apt-get -yqq update
RUN apt-get -yqq install wget
VOLUME [ "/var/lib/tomcat7/webapps/" ]
WORKDIR /var/lib/tomcat7/webapps/
ENTRYPOINT [ "wget" ]
CMD [ "-?" ]
This incredibly simple image does one thing: it wgets whatever fle from a URL
that is specifed when a container is run from it and stores the fle in the /var/lib
/tomcat7/webapps/ directory. This directory is also a volume and the working
directory for any containers. We’re going to share this volume with our Tomcat
server and run its contents.
Finally, the ENTRYPOINT and CMD instructions allow our container to run when no
URL is specifed; they do so by returning the wget help output when the container
is run without a URL.
Can anyboy tell me what's the meaning of "CMD [ "-?" ]"
I know the concept of ENTRYPOINT and CMD,
what I don't understand is the meaning of "-?" in "wget -?"
When you run a Docker container, it constructs a command line by simply concatenating the "entrypoint" and "command". Those come from different places in the docker run command line; but if you don't provide a --entrypoint option then the ENTRYPOINT in the Dockerfile is used, and if you don't provide any additional command-line arguments after the image name then the CMD is appended.
So, a couple of invocations:
# Does "wget -?"
docker run --rm thisimage
# Does "wget -O- http://stackoverflow.com": dumps the SO home page
docker run --rm thisimage -O- http://stackoverflow.com
# What you need to do to get an interactive shell
docker run --rm -it --entrypoint /bin/sh thisimage
I figure it out, The author made a clerical error. The arguments in CMD should be "-h".
Because in the later he said " Finally, the ENTRYPOINT and CMD instructions allow our container to run when no URL is specifed; they do so by returning the wget help output when the container is run without a URL."

How to pass command line arguments to my dockerized python app

I have a simple docker file which I am using to containerize my python app. The app actually takes file paths as command line arguments. It is my first time using Docker and I am wondering how I can achieve this:
FROM python:3.6-slim
COPY . /app
WORKDIR /app
RUN apt-get update && apt-get -y install gcc g++
# Install numpy, pandas, scipy and scikit
RUN pip install --upgrade pip
RUN pip --no-cache-dir install -r requirements.txt
RUN python setup.py install
ENTRYPOINT python -m myapp.testapp
Please note that the python app is run from the from the module with the -m flag.
This builds the image completely fine. I can also run it using:
docker run -ti myimg
However, I cannot pass any command line arguments to it. For example, my app prints some help options with the -h option.
However, running docker as:
docker run -ti myimg -h
does not do anything. So, the command line option are not being passed.
Additionally, I was wondering what the best way to actually pass file handles from the host computer to docker. So, for example, the application takes path to a file as an input and the file would usually reside on the host computer. Is there a way for my containerized app to be able to access that?
You have to use the CMD instruction along with ENTRYPOINT(in exec form)
ENTRYPOINT ["python", "-m", "myapp.testapp"]
CMD [""]
Make sure whatever default value you are passing to CMD, ("" in the above snippet), it is ignored by your main command
When you do, docker run -ti myimg,
the command will be executed as python -m myapp.testapp ''
When you do, docker run -ti mying -h,
the command will be executed as python -m myapp.testapp -h
Note:
exec form: ENTRYPOINT ["command", "parameter1", "parameter2"]
shell form: ENTRYPOINT command parameter1 parameter2

Resources