4

I want to copy a file generated by a docker container, and store inside it to my local host. What is a good way of doing that? The docker container is ephemeral (i.e. it runs for a very short time and then stops.)

I am working with the below mentioned scripts:

Python (script.py) which generates and saves a file titled read.txt.

with open('read.txt', 'w') as file:
    lst = ['Some\n',
             'random\n',
             'sentence\n']

    file.writelines("% s\n" % words for words in lst)

I use the below Dockerfile:

FROM python:3.9

WORKDIR /app

RUN pip install --upgrade pip
COPY . /app/
RUN pip install --requirement /app/requirements.txt
CMD ["python", "/app/script.py.py"]

Below is my folder structure:

- local
    - folder1
        - script.py
        - requirements.txt
        - Dockerfile
    - folder2

Till now, I have managed to successfully build a docker container using:

docker build --no-cache -t test:v1 .

When I run this docker container inside /local/folder1/ using the below command, I get the desired file, i.e. read.txt inside /local/folder1/

docker run -v /local/folder1/:/app/ test:v1

But, when I run docker run -v /local/folder2/:/app/ test:v1 inside /local/folder2/, I do not see read.txt inside /local/folder2/ and I get the below message.

python: can't open file '/app/script.py': [Errno 2] No such file or directory

I want to be able to get read.txt inside /local/folder2/ when I run the docker container test:v1 inside /local/folder2/. How can I do it? I want to be able to do it without copying the contents of /local/folder1/ inside /local/folder2/.

The docker container is ephemeral (i.e. it runs for a very short time and then stops.) Hence answers given in this and this Stackoverflow posts, which focus on docker cp have not worked for me.

Time of running of the abovementioned container is not very essential. Even if a workable solution increases the time of running of a container, that is okay.

Mike 'Pomax' Kamermans
  • 49,297
  • 16
  • 112
  • 153
Ling Guo
  • 592
  • 4
  • 12
  • 1
    Take a look at [scuba](https://github.com/JonathonReinhart/scuba), a tool I wrote for doing things with the current directory in a docker container. – Jonathon Reinhart Aug 17 '23 at 00:03
  • Your host system probably has Python installed already. Can you just run the second process as an ordinary subprocess, without involving Docker at all? Do any of the recipes in [Copying files from Docker container to host](https://stackoverflow.com/questions/22049212/copying-files-from-docker-container-to-host) help you? – David Maze Aug 17 '23 at 00:37

2 Answers2

2

Since the container is ephemeral, you may want to run the container and keep it running. And then copy the file.

Try the below steps:

1. Keep the container running and run the python command.

docker run -it --name temp test:v1 bash -c 'python script.py'

Here temp is the name of a temporary container.

2. Copy file from temp container to local host.

docker cp temp:/app/read.txt /local/folder2/.

3. Remove the temporary container.

docker rm temp
Siddharth Satpathy
  • 2,737
  • 4
  • 29
  • 52
0

The problem is: there's overlap between a mounted path and image's already existing filesystem, docker will choose to not override your host's (laptop etc) filesystem. So in folder1 you were actually running the python code from your host's filesystem. To verify this you can change the script.py (add a new output line for file etc) and without building a new image, run the old one. You'll have different output.

How to fix:

Simplest way

Just create another directory for output:

FROM python:3.9

WORKDIR /app
RUN mkdir /output

RUN pip install --upgrade pip
COPY . /app/
RUN pip install --requirement /app/requirements.txt
CMD ["python", "/app/script.py"]

Change python script to write to /output/read.txt

with open('/output/read.txt', 'w') as file:
    lst = ['Somee\n',
             'random\n',
             'sentence\n']

    file.writelines("% s\n" % words for words in lst)

Then mount output directory to folder2.

docker run -v /local/folder2/:/output/ test:v1

More generic ways

You can choose output directory from environment variable and set via ENV in Dockerfile. Maybe use of ARG can be good use case for you.

Disclaimer for the obvious simplest way

Usage of /tmp may cause problem that you never thought, some programs use sentinel files instead of IPC because you /tmp is mounted to host it'll override initial state of /tmp (I'm not sure it'll be ever problem but it may...)

Umut Gerçek
  • 630
  • 6
  • 9