Even more so: this implies that Python, which is looking for main.app
in WORKDIR /app
will always be using the first version of your application code once that was copied into the volume, even if you build a new image afterwards. Like when using the official Python base image, with a Dockerfile like:
FROM python:3
WORKDIR /app
COPY . .
CMD ["python", "./main.py"]
With the above Dockerfile, the following creates a main.py
with only print('Hello world')
, executes the first Docker build, and runs the container for the first time using a new, empty, volume:
echo "print('Hello world')" > main.py
docker build -t mytest .
# This will create "myvolume" if it does not exist yet
docker run --rm -v myvolume:/app mytest
Hello world
So far, so good. Or, so it seems! See what happens when changing main.py
to print something different, but while mounting the same existing volume to /app
:
echo "print('Goodbye world')" > main.py
docker build -t mytest .
# This will mount the existing "myvolume" to /app, holding the old main.py
docker run --rm -v myvolume:/app mytest
Hello world
Next, removing the volume and running the very same image, which now will create a new empty volume again and copy the updated contents of /app
from the last image into that:
docker volume rm myvolume
docker run --rm -v myvolume:/app mytest
Goodbye world
(Clean up after the above: docker volume rm myvolume
.)
I doubt your users need access to the application code in the container? So make your application write its output to something like /data
, not to /app
, and only share that /data
. In fact, make that a configuration which you can access using os.environ
or os.getenv
, like os.getenv("MYNAME", "world")
:
echo "import os\nprint(f'Hello {os.getenv(\"MYNAME\", \"world\")}')" > main.py
docker build -t mytest .
docker run --rm mytest
Hello world
docker run --rm -e MYNAME=ilzhuu mytest
Hello ilzhuu
I missed this question from an earlier post:
For bind mounts, you are sharing an existing folder (or file) on your host machine with Docker. Anything the application in the Docker container does with that shared folder will simply be visible in that host folder. And the other way around: if you change something on the host machine then the application in the container can see that. So, if you share your $HOME
folder using a bind mount, then the application has direct access to everything in the user’s home folder. See Bind mounts | Docker Docs.
Just to be sure: note that the name in the container does not need to be the same as the original folder: using, say, -v $HOME/my/folder:/data
shares the host directory /home/ilze/my/folder
and makes it available as (“mounts it as”) /data
in the container. You can even share the very same host folder (or volume) to multiple locations in the container, like -v $HOME/my/folder:/input -v $HOME/my/folder:/output
would show two folders /input
and /output
in the container, which would both map to the same folder on the host. In the container, the two folders would also show the same files; if the application creates a file in /output
it would also see it in /input
.
(Same goes for volumes: in your very first post, using -v volume1:/home/ilze/PycharmProjects/pythonProject
made the volume available in the container as /home/ilze/PycharmProjects/pythonProject
, which matched the name on your host machine, but really did have nothing to do with that folder on the host. If you would have used -v volume1:/some/other/folder
then the same volume would have been available in the container as /some/other/folder
.)