Run command on entrypoint in docker outputs no file errors - docker

On a simple dockerfile:
FROM python:3
ENV PYTHONUNBUFFERED 1
WORKDIR /code/
If I run:
docker build -t my_image .
docker run -v ~/Downloads/data/:/home -it -d my_image # mount data folder inside home
docker exec -it container_id sh -c "python script.py -i /home/db.sqlite"
Everything runs ok. But I would like to run the script.py on run so that there is no need for an exec command.
So I added to the dockerfile:
ENTRYPOINT ["python script.py -i /home/db.sqlite"]
But when I run my container now it fails with a file or folder not found error at python script.py

I think the problem is how the ENTRYPOINT syntax works. Your using the exec-form and it does not find the binary (it uses the whole command line as path to the binary).
From https://docs.docker.com/engine/reference/builder/#entrypoint:
ENTRYPOINT has two forms:
ENTRYPOINT ["executable", "param1",
"param2"] (exec form, preferred)
ENTRYPOINT command param1 param2
(shell form)
So try either:
ENTRYPOINT ["/path/to/python", "script.py", "-i", "/home/db.sqlite"]
Or
ENTRYPOINT python script.py -i /home/db.sqlite

Related

Append argument to ENTRYPOINT in Docker run where some args are already defined

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

docker run --entrypoint "python /path/to/file.py" cause "no such file or directory: unknown." error

Running docker run -it --entrypoint "bash" fnb-backend and then python /app/main/src/api/frontend/customer_api/customer_api.py in container shell works fine.
Consider Dockerfile below:
FROM python:2.7.18-slim
COPY main/requirements.txt .
RUN cat requirements.txt | xargs -n 1 pip install --no-cache-dir; exit 0
ENV PYTHONUNBUFFERED True
COPY . ./app/
RUN mkdir -p /app/main/logs/flask/ && touch /app/main/logs/flask/webhook_api.log
# below works
#ENTRYPOINT python /app/main/src/api/frontend/customer_api/customer_api.py
The commented out line works fine too.
However running docker run --entrypoint "python /app/main/src/api/frontend/customer_api/customer_api.py" fnb-backend cause:
docker: Error response from daemon: OCI runtime create failed: container_linux.go:367: starting container process caused: exec: "python /app/main/src/api/frontend/customer_api/customer_api.py": stat python /app/main/src/api/frontend/customer_api/customer_api.py: no such file or directory: unknown.
ERRO[0000] error waiting for container: context canceled
What you used in Dockerfile is shell form of ENTRYPOINT, see next:
ENTRYPOINT command param1 param2
What you used in docker run using --entrypoint could override the command of ENTRYPOINT in Dockerfile, this means it can just act as command, not the syntax of command param1 param2, see next:
Passing --entrypoint will clear out any default command set on the image
In fact, for --entrypoint, docker will treat it as a whole command, so if you use command param1 param2, it will try to find the executable of command param1 param2, it will result file not found.
For you, the correct way is next which put params to command of docker run:
docker run --entrypoint python fnb-backend /app/main/src/api/frontend/customer_api/customer_api.py

run script in Dockerfile

I have to run my .sh script in Dockerfile based on "grafana/grafana" but I'm not sure how to do it.
FROM grafana/grafana
COPY setup.sh /setup.sh
CMD ["/bin/bash", "/setup.sh"]
after docker run my script is not running. I guess it due to in grafana Dockerfile runs another sh script.
Can you please try if that works:
RUN ./setup.sh
There are two ways to do it inside Dockerfile
RUN <command> (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows)
RUN ["executable", "param1", "param2"] (exec form)

How to pass dynamic values to Docker container?

I am running a perl script in Dockerfile and I would like to pass dynamic command line arguments to the perl script while running docker image(container).
Ex: CMD perl test.pl <args>. I am new to Docker.
Is there any possible way to pass dynamic values to the docker container like
docker run <image name> <args>?
You could use an Entrypoint script:
$ docker run [OPTIONS] IMAGE[:TAG|#DIGEST] [COMMAND] [ARG...]
and
If the image also specifies an ENTRYPOINT then the CMD or COMMAND get appended as arguments to the ENTRYPOINT.
So depending on your Dockerfile you'd have something like this (python sample app):
FROM jfloff/alpine-python:3.6
# add entrypoint script
USER root
COPY start.sh /
RUN chmod a+x /start.sh
ENTRYPOINT ["/start.sh"]
CMD ["arg1"]
and start.sh:
#!/bin/bash
echo $1
# don't exit
/usr/bin/tail -f /dev/null
Now you can do something like:
15:19 $ docker run f49b567f05f1 Hello
Hello
15:21 $ docker run f49b567f05f1
arg1
Now if your script is set up to take those arguments, you should be able to run it as you want. Reference from Docker is attached, search for "Overriding Dockerfile image defaults" in this and then look in the CMD section.
Or check this Post.
I am not sure whether you can do it with CMD but if you just want to execute the perl script with some passed in arguments use ENTRYPOINT.
ENTRYPOINT ["perl", "test.pl"]
CMD ["default-arg"]
Run the container with:
docker -run <image-name> overriding-arg

Passing arguments from CMD in docker

I have got below Dockerfile.
FROM node:boron
# Create app directory
RUN mkdir -p /usr/src/akamai
WORKDIR /usr/src/akamai
# Install app dependencies
COPY package.json /usr/src/akamai/
RUN npm install
# Bundle app source
COPY . /usr/src/akamai
#EXPOSE 8080
CMD ["node", "src/akamai-client.js", "purge", "https://www.example.com/main.css"]
Below is the command which I run from CMD after the docker image build
docker run -it "akamaiapi" //It executes the CMD command as given in above Dockerfile.
CMD ["node", "src/akamai-client.js", "purge", "https://www.example.com/main.css"] //I want these two arguments directly passed from docker command instead hard-coded in Dockerfile, so my Docker run commands could be like these:
docker run -it "akamaiapi" queue
docker run -it "akamaiapi" purge "https://www.example.com/main.css"
docker run -it "akamaiapi" purge-status "b9f80d960602b9f80d960602b9f80d960602"
You can do that through a combination of ENTRYPOINT and CMD.
The ENTRYPOINT specifies a command that will always be executed when the container starts.
The CMD specifies arguments that will be fed to the ENTRYPOINT.
So, with Dockerfile:
FROM node:boron
...
ENTRYPOINT ["node", "src/akamai-client.js"]
CMD ["purge", "https://www.example.com/main.css"]
The default behavior of a running container:
docker run -it akamaiapi
would be like command :
node src/akamai-client.js purge "https://www.example.com/main.css"
And if you do :
docker run -it akamaiapi queue
The underlying execution in the container would be like:
node src/akamai-client.js queue

Resources