I have created a docker image from a Dockerfile. Projects working perfectly. I've a few tests and to invoke those tests I've created a run_tests.sh file, I've made the file executable too.
So, when I run docker run -it --rm <image_name> run_tests.sh
it should output the test result, instead it outputting server ip address it listening to.
How to run bash script from a Docker Image without entering it's shell?
This is my Dockerfile...
FROM python:3.8-slim-buster
RUN pip install --upgrade pip
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
WORKDIR /app
COPY requirements.txt /app/requirements.txt
# install dependencies
RUN pip install -r requirements.txt
RUN apt-get update
RUN apt-get install gnupg -y
# copy project
COPY . /app/
# making executable test file and entrypoint file for bash shell
RUN chmod x run_tests.sh
RUN chmod x entrypoint.sh
COPY ./entrypoint.sh /
ENTRYPOINT ["sh", "/entrypoint.sh"]
CodePudding user response:
Here's a list of things to check:
Use CMD
and not ENTRYPOINT
in the Dockerfile. The command after the docker run
image name overrides the Dockerfile CMD
, and if both an ENTRYPOINT
and a CMD
are present then the CMD
gets passed as arguments to the ENTRYPOINT
. You can work around this using docker run --entrypoint
as described in @MarcosParreiras's answer but there's no benefit to using ENTRYPOINT
here; just use CMD
instead.
CMD ["sh", "/entrypoint.sh"]
Make sure your script can execute normally. It should be executable (as in chmod x
), and it should begin with a "shebang" line
#!/bin/sh
# ^^^ as the very very first thing in the script
Outside Docker you should be able to run ./run_tests.sh
and it should run without explicitly naming an interpreter. If the file is executable on the host (and checked into source control as executable) then Dockerfile COPY
will preserve the executable bit and you don't need to RUN chmod
in the Dockerfile.
(You can do the same thing with your entrypoint.sh
script and omit the explicit sh
interpreter from the CMD
.)
Put the script in $PATH
somewhere. /usr/local/bin
is often a good choice.
(In a Python context, if your setup.cfg
file contains setuptools entry points, then pip install
will put its wrapper scripts into /usr/local/bin
and you can just run them; this is done automatically.)
Putting these all together, you'd get a Dockerfile like:
COPY entrypoint.sh run_tests.sh /usr/local/bin
# RUN chmod x /usr/local/bin/*
CMD ["entrypoint.sh"]
And you should be able to run exactly the docker run
command you initially proposed
docker run -it --rm image_name run_tests.sh
CodePudding user response:
You can run achieve that by running:
docker run --rm --entrypoint '' <image_name> /bin/bash -c './run_tests.sh'
or
docker run --rm --entrypoint '' <image_name> sh -c './run_tests.sh'
in case your image has only sh
available
In either case, you are just running a container from the desired image and then running either /bin/bash
or sh
with the -c
flag, that allows you to define the command to run from a string. Also, by setting --entrypoint ''
, you are overriding the default entrypoint set on the Dockerfile. When you have an entrypoint set, the docker command would be appended as parameters for that, so we override the entrypoint to be an empty one.
Also, you should no use the options -it
in this case, given that they are used when you want to interact with the container (i.e access the terminal within the container).