It's just a theoretical question. Is there a way to run the docker but only run one specific script without changing the Dockerfile? Maybe with the docker run [container]
command?
Dockerfile:
FROM python:3.8
ADD main1.py
ADD main2.py
ADD main3.py
ADD main4.py
ADD main5.py
Theoretical Command:
docker run docker-test main2.py
CodePudding user response:
There is nothing "theoretical" about this. Docker copies into place the files, and if they are working executables, you can execute them with docker run image executable
... but
it requires the files to be properly executable (or you will need to explicitly say
docker run image python executable
to run a Python script which is not executable)it requires the files to be in your
PATH
for you to be able to specify their names without a path; or you will need to specify the full path within the container, or perhaps a relative path (./executable
if they are in the container's default working directory)docker run image /path/to/executable
you obviously need the container to contain
python
in itsPATH
in order for it to findpython
; or you will similarly need to specify the full path to the interpreterdocker run image /usr/bin/python3 /path/to/executable
In summary, probably make sure you have chmod x
the script files and that they contain (the moral equivalent of) #!/usr/bin/env python3
(or python
if that's what the binary is called) on their first line.
(And obviously, don't use DOS line feeds in files you want to be able to execute in a Linux container. Python can cope but the Linux kernel will look for /usr/bin/env python3^M
if that's exactly what it says on the shebang line.)
CodePudding user response:
In the specific case of a Python application, the standard Python setuptools package has some functionality that can simplify this.
In your application's setup.cfg
file you can declare entry points (different from the similarly-named Docker concept) which provide simple scripts to launch a specific part of your application.
[options.entry_points]
console_scripts =
main1 = app.main1:main
main2 = app.main2:main
where the scripts app/main1.py
look like normal top-level Python scripts
#!/usr/bin/env python3
# the console_scripts call this directly
def main():
...
# for interactive use
if __name__ == '__main__':
main()
Now in your Dockerfile, you can use a generic Python application recipe and install this; all of the console_scripts
will be automatically visible in the standard $PATH
.
FROM python:3.8
WORKDIR /app
COPY . .
RUN pip install .
CMD ["main1"]
docker run --rm my-image main2
It's worth noting that, up until the last part, we've been using generic Python utilities, and you can do the same thing without Docker
# directly on the host, without Docker
python3 -m venv ./virtual_environment
. ./virtual_environment/bin/activate
pip install .
# then run any of the scripts directly
main3
# technically activating the virtual environment is optional
deactivate
./virtual_environment/bin/main4
The fundamental point here is that the same rules apply for running a command on the host, in a Dockerfile CMD
, or in a docker run
command override (must be on $PATH
, executable, have the correct interpreter, etc.). See @tripleee's answer for a more generic, non-Python-specific approach.