I have problem with my Dockerfile.
I want to execute my python script during image building (this script creates a few files).
But this script is not execute during image building - there aren't file created by script in container.
It's my Dockerfile
FROM ubuntu:latest
RUN python script1.py
If you need to interact with files during image building, you must add those files to the image first, otherwise how is Docker to know where those files are?
FROM ubuntu:latest
ADD script1.py /tmp/script1.py
RUN python /tmp/script1.py
Of course, I'll leave the paths to you.
FROM ubuntu:latest
ADD script1.py /tmp/script1.py #add/copy files from some path
CMD ["python", "/tmp/script1.py"] # to run python with provided script/argument
Related
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
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 its PATH in order for it to find python; or you will similarly need to specify the full path to the interpreter
docker 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.)
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.
I am trying to write a text (.txt) file to a local Desktop folder on Windows 10 after building a docker image (docker_run_test). The docker build seems to work seamlessly using "docker build -t docker_run_test .", running the command from the working directory on the Desktop where the Dockerfile and Python script reside (C:/Users/mdl518/Desktop/docker_tests/). The script is a simple print statement and writing of the print statement to a .txt file, but I cannot locate the output .txt. Below is the associated Dockerfile, and the Python script.
The Dockerfile:
FROM python:3
ADD docker_test.py ./
RUN pip install pandas
CMD ["python3","./docker_test.py"]
The Python script (docker_test.py):
import os
print("This is a Docker test.")
with open('docker_test.txt', 'w') as f:
f.write("This is a Docker test.")
I have searched the contents of the Docker image as well, but cannot locate the output .txt within the image either. Any assistance is most appreciated!
You have to mount/bind the folder where you want to see the results into the container.
Change the output filename to write in another folder, let say /output
with open('/output/docker_test.txt', 'w') as f:
And then ask Docker to bind host folder %HOMEPATH%\Desktop to container /output :
docker run -v %HOMEPATH%\Desktop:/output docker_run_test
Not sure for %HOMEPATH% syntax as I'm a Linux user.
I have a Python script, python_script.py, that reads an HDF5 file, hdf_file.h5, on my local machine. The directory path to the files is
folder1
folder2
python_script.py
hdf_file.h5
I have the following sample code:
from pandas import read_hdf
df = read_hdf('hdf_file.h5')
When I run this code on my local machine, it works fine.
However, I need to place the Python script inside a Docker container, keep the HDF file out of the container, and have the code read the file. I want to have something like the following directory path for the container:
folder1
folder2
hdf_file.h5
docker-folder
python_script.py
requirements.txt
Dockerfile
I use the following Dockerfile:
FROM python:3
WORKDIR /project
COPY ./requirements.txt /project/requirements.txt
RUN pip install -r requirements.txt
COPY . /project
CMD [ "python", "python_script.py" ]
I am new to Docker and am having a lot of trouble figuring out how to get a Python script inside a container to read a file outside the container. What commands do I use or code changes do I make to be able to do this?
It seems you need to use docker volumes (https://docs.docker.com/storage/volumes/).
Try the following:
docker run -v path/where/lives/hdf5/:path/to/your/project/folder/your_image your_docker_image:your_tag
Where the first part before the : refers to host machine and after, the container.
Hope it helps!
This question is ought to have been asked before but I can't find an answer. I am running a python script from my terminal using docker, like:
docker run --rm img_name -v local_path:docker_path python docker_path_to_script/script.py
when I print from script.py where the script thinks it is using cmd it says:
/
which makes no sense (not sure what the official name of that is). This causes problems cuz I have relative paths within script.py. How do I have the script run from the correct location inside docker?
Set the default WORKDIR in the image build
WORKDIR /docker_path
Set WORKDIR with -w when running the image
docker run -w /docker_path IMAGE COMMAND
A very simple Python program. Suppose the current directory is /PYTHON. I want to pass file.txt as an argument to the Python script boot.py. Here is my Dockerfile:
FROM python
COPY boot.py ./
COPY file.txt ./
RUN pip install numpy
CMD ["python", "boot.py", "file.txt"]
Then I build the Docker container with:
docker build -t boot/latest .
Then run the container
docker run -t boot:latest python boot.py file.txt
I got the correct results.
But if I copy another file, file1.txt, to the current directory (from a different directory (not /PYTHON)), then I run the container again:
docker run -t boot:latest python boot.py file1.txt
I got the following error:
FileNotFoundError: [Errno 2] No such file or directory: 'file1.txt'
so the error is due to fact that file1.txt is not in the container, but if I share this container with a friend and the friend wants to pass a very different file as argument, how do I write the Dockerfile so anybody with my container can pass very different files as argument without errors?
It won't work that way. Like you said, file1.txt is not in the container.
The workaround is to use Docker volumes to inject files from your host machine to the container when running it.
Something like this:
docker run -v /local/path/to/file1.txt:/container/path/to/file1.txt -t boot:latest python boot.py /container/path/to/file1.txt
Then /local/path/to/file1.txt would be the path on your host machine which will override /container/path/to/file1.txt on the container.
You may also make your script read from STDIN and then pass data to docker using cat. Have a look at how to get docker container to read from stdin?
The trick is to keep STDIN open even if not attached with
--interactive or -i (alias) option for Docker.
Something like:
cat /path/to/file | docker run -i --rm boot python boot.py
Or:
docker run -i --rm boot python booty.py < /path/to/file
EOF is the end of the input.
If I understand the question correctly, you are acknowledging that the file isn't in the container, and you are asking how to best share you container with the world, allowing people to add their own content into it.
You have a couple of options, either use Docker volumes, which allows your friends (and other interested parties) to mount local volumes inside your Docker containers. That is, you can overlay a folder on your local filesystem onto a folder inside the container (this is generally quite nifty when you are developing locally as well).
Or, again, depending on the purpose of your container, somebody could extend your image. For example, a Dockerfile like
FROM yourdockerimage:latest
COPY file1.txt ./
CMD ["python", "boot.py", "file1.txt"]
Choose whichever option suits your project the best.
One option is to make use of volumes.
This way all collaborators on the project are able to mount them in the containers.
You could change your Dockerfile to:
FROM python
COPY boot.py ./
COPY file.txt ./
RUN pip install numpy
ENTRYPOINT ["python", "boot.py"]
And then run it to read from STDIN:
docker run -i boot:latest -<file1.txt