Moving file from docker to local while inside docker container - python

I'm having a python program that stores the output file in local. Now my code is run inside docker container I want to move the generated output file (like output.txt) to my local (outside the docker container)
I know there is a command which transfers files from docker to local:
docker cp <containerId>:/file/path/within/container /host/path/target
#I tried like this inside docker container but it didn't work
os.system(sudo docker cp <containerId>:/file/path/within/container /host/path/target)
But since my program is executing inside docker this doesn't work and I want to push the file to local as the code runs.
If you have any ideas please share them.

There is no way for code inside a container to directly manipulate anything outside the container. The whole purpose of a container is to isolate it from the host system; breaking this barrier would have grave security consequences, and basically render containers pointless.
What you can do is mount a directory from the host inside the container with -v (or run docker cp from outside the container once you are confident it has succeeded in creating the file successfully; but then how would you communicate this fact to the outside?)
With
docker run --volume=`pwd`:/app myimage
you can
cp myfile /app
inside the container; this will create ./myfile from within Docker.

Treat container as a Linux system, your question will consider as: how transfer files between two hosts.
Maybe there are some another ways without rerun the container:
scp(recommend) with other options or tools while you need, like expect could handle the ssh's accept fingerprint or input the password, assume 172.17.0.1 is the host's docker interface and ssh_port is 22 by default, and the ssh progress is listening the docker interface such as 0.0.0.0:22.
os.system(sudo scp /file/path/within/container user#172.17.0.1:/host/path/target)
other client–server models, such as rsync(client and server), python SimpleHTTPServer(server) and curl | python request | wget(client) and so on. But these are not recommend, because the server and client need to deploy.

Related

Make call to my local machine using os.system() from within a docker container

Docker for Windows.
I've written a docker image for a python project.
When I start a container based on this image, one of the instructions that gets executed is the following:
os.system(f"start \"\" "path/to/pdf_file.pdf")
which simply opens the specified PDF file with the default PDF opener.
This instruction works perfectly locally, but, if I run it from a docker container, this file doesn't get opened in my local machine.
This makes sense, it probably gets opened in the docker container, and I can't see it because I've no way of seeing what's going on in the container (except by looking at the container logs).
My goal is to have the docker container TELL to my local machine to execute that command, in such a way the PDF file gets opened in my local machine, not in the docker container.
How could I achieve such goal?

Is there a way to copy the file contents from a different containers to host file system?

I'm trying to copy the text file from a docker container to a host file system. We can do this using the docker cp command but the real issue is : There is a possibility that there might be a different container of the same image because my virtual machine will restart after sometime. And there will be a different container id for the same image when I restart my machine.
I have to include this commands in the python script and so I can not change the container ID explicitly.
I have tried the docker cp command in which we have to mention the container id.
def function():
write some data into the file.
file.close()
"""
I need to execute commands or bash script here so that file I have
created in the container can be copied to host file system given
container id will change because of the machine restart.
"""

Share directory in docker container with parent scope docker container in gitlab-ci?

I am using a volume when running a docker container with something like docker run --rm --network host --volume $PWD/some_dir:/tmp/some_dir .... Inside the container I am running Python code which creates the directory /tmp/some_dir (overrides it in case it's already there) and puts files into there. If I run the docker container on my local dev machine the files are available on my dev machine in /tmp/some_dir after running the container.
However if I run the same container as part of a gitlab-ci job ("docker in docker", the container is not the image used for the job itself) the files are not accessible in /tmp/some_dir (the directory exists).
What could be a reason for the missing files?
The first half of the docker run -v option, if it's a directory path, is a directory specifically on the host machine. If a container has access to the Docker socket and launches another container, any directory mappings it provides are in the host filesystem's space, not the container filesystem's space. (If you're actually using Docker-in-Docker it is probably the filesystem space of the container running the nested Docker daemon, but it's still not the calling container's filesystem space.)
The most straightforward option is to docker cp files out of the inner container after it's stopped but before you docker rm it; it can copy a whole directory tree.
Did you checked the good directory on the good server ?
Creating a $PWD/some_dir in a DinD context, The result should be in a some_dir created in docker user home dir in the server running Gitlab CI container.

How to use data in a docker container?

After installing Docker and googling for hours now, I can't figure out how to place data in a Docker, it seems to become more complex by the minute.
What I did; installed Docker and ran the image that I want to use (kaggle/python). I also read several tutorials about managing and sharing data in Docker containers, but no success so far...
What I want: for now, I simply want to be able to download GitHub repositories+other data to a Docker container. Where and how do I need to store these files? I prefer using GUI or even my GitHub GUI, but simple commands would also be fine I suppose.. Is it also possible to place data or access data from a Docker that is currently not active?
Note that I also assume you are using linux containers. This works in all platforms, but on windows you need to tell your docker process that that you are dealing with linux containers. (It's a dropdown in the tray)
It takes a bit of work to understand docker and the only way to understand it is to get your hands dirty. I recommend starting with making an image of an existing project. Make a Dockerfile and play with docker build . etc.
To cover the docker basics (fast version) first.
In order to run something in docker we first need to build and image
An image is a collection of files
You can add files to an image by making a Dockerfile
Using the FROM keyword on the first line you extend and image
by adding new files to it creating a new image
When staring a container we need to tell what image it should use
and all the files in the image is copied into the containers storage
The simplest way to get files inside a container:
Crate your own image using a Dockerfile and copy in the files
Map a directory on your computer/server into the container
You can also use docker cp, to copy files from and two a container,
but that's not very practical in the long run.
(docker-compose automates a lot of these things for you, but you should probably also play around with the docker command to understand how things work. A compose file is basically a format that stores arguments to the docker command so you don't have to write commands that are multiple lines long)
A "simple" way to configure multiple projects in docker in local development.
In your project directory, add a docker-dev folder (or whatever you want to call it) that contains an environment file and a compose file. The compose file is responsible for telling docker how it should run your projects. You can of course make a compose file for each project, but this way you can run them easily together.
projects/
docker-dev/
.env
docker-compose.yml
project_a/
Dockerfile
# .. all your project files
project_b/
Dockerfile
# .. all your project files
The values in .env is sent as variables to the compose file. We simply add the full path to the project directory for now.
PROJECT_ROOT=/path/to/your/project/dir
The compose file will describe each of your project as a "service". We are using compose version 2 here.
version: '2'
services:
project_a:
# Assuming this is a Django project and we override command
build: ${PROJECT_ROOT}/project_a
command: python manage.py runserver 0.0.0.0:8000
volumes:
# Map the local source inside the container
- ${PROJECT_ROOT}/project_a:/srv/project_a/
ports:
# Map port 8000 in the container to your computer at port 8000
- "8000:8000"
project_a:
# Assuming this is a Django project and we override command
build: ${PROJECT_ROOT}/project_b
volumes:
# Map the local source inside the container
- ${PROJECT_ROOT}/project_b:/srv/project_b/
This will tell docker how to build and run the two projects. We are also mapping the source on your computer into the container so you can work on the project locally and see instant updates in the container.
Now we need to create a Dockerfile for each out our projects, or docker will not know how to build the image for the project.
Example of a Dockerfile:
FROM python:3.6
COPY requirements.txt /requirements.txt
RUN pip install requirements.txt
# Copy the project into the image
# We don't need that now because we are mapping it from the host
# COPY . /srv/project_a
# If we need to expose a network port, make sure we specify that
EXPOSE 8000
# Set the current working directory
WORKDIR /srv/project_a
# Assuming we run django here
CMD python manage.py runserver 0.0.0.0:8000
Now we enter the docker-dev directory and try things out. Try to build a single project at a time.
docker-compose build project_a
docker-compose build project_b
To start the project in background mode.
docker-compose up -d project_a
Jumping inside a running container
docker-compose exec project_a bash
Just run the container in the forground:
docker-compose run project_a
There is a lot of ground to cover, but hopefully this can be useful.
In my case I run a ton of web servers of different kinds. This gets really frustrating if you don't set up a proxy in docker so you can reach each container using a virtual host. You can for example use jwilder-nginx (https://hub.docker.com/r/jwilder/nginx-proxy/) to solve this in a super-easy way. You can edit your own host file and make fake name entires for each container (just add a .dev suffix so you don't override real dns names)
The jwilder-nginx container will automagically send you to a specific container based on a virtualhost name you decide. Then you no longer need to map ports to your local computer except for the nginx container that maps to port 80.
For others who prefer using GUI, I ended up using portainer.
After installing portainer (which is done by using one simple command), you can open the UI by browsing to where it is running, in my case:
http://127.0.1.1:9000
There you can create a container. First specify a name and an image, then scroll down to 'Advanced container options' > Volumes > map additional volume. Click the 'Bind' button, specify a path in the container (e.g. '/home') and the path on your host, and you're done!
Add files to this host directory while your container is not running, then start the container and you will see your files in there. The other way around, accessing in files created by the container, is also possible while the container is not running.
Note: I'm not sure whether this is the correct way of doing things. I will, however, edit this post as soon as I encounter any problems.
After pulling the image, you can use code like this in the shell:
docker run --rm -it -p 8888:8888 -v d:/Kaggles:/d kaggle/python
Run jupyter notebook inside the container
jupyter notebook --ip=0.0.0.0 --no-browser
This mounts the local directory onto the container having access to it.
Then, go to the browser and hit https://localhost:8888, and when I open a new kernel it's with Python 3.5/ I don't recall doing anything special when pulling the image or setting up Docker.
You can find more information from here.
You can also try using datmo in order to easily setup environment and track machine learning projects to make experiments reproducible. You can run datmo task command as follows for setting up jupyter notebook,
datmo task run 'jupyter notebook' --port 8888
It sets up your project and files inside the environment to keep track of your progress.

I'm having trouble using docker-py in a development environment on OSX

I am creating Python code that will be built into a docker image.
My intent is that the docker image will have the capability of running other docker images on the host.
Let's call these docker containers "daemon" and "workers," respectively.
I've proven that this concept works by running "daemon" using
-v /var/run/docker.sock:/var/run/docker.sock
I'd like to be able to write the code so that it will work anywhere that there exists a /var/run/docker.sock file.
Since I'm working on an OSX machine I have to use the Docker Quickstart terminal. As such, on my system there is no docker.sock file.
The docker-py documentation shows this as the way to capture the docker client:
from docker import Client
cli = Client(base_url='unix://var/run/docker.sock')
Is there some hackery I can do on my system so that I can instantiate the docker client that way?
Can I create the docker.sock file on my file system and have it sym-linked to the VM docker host?
I really don't want to have to build my docker image every time I was to test a single line code change... help!!!

Categories