Docker mount volume to reflect container files in host - docker

The use case is that I want to download and image that contains python code files. Assume the image does not have any text editor installed. So i want to mount a drive on host, so that files in the container show up in this host mount and i can use different editors installed on my host to update the code. Saving the changes are to be reflected in the image.
if i run the following >
docker run -v /host/empty/dir:/container/folder/with/code/files -it myimage
the /host/empty/dir is still empty, and browsing the container dir also shows it as empty. What I want is the file contents of /container/folder/with/code/files to show up in /host/empty/dir

Sébastien Helbert answer is correct. But there is still a way to do this in 2 steps.
First run the container to extract the files:
docker run --rm -it myimage
In another terminal, type this command to copy what you want from the container.
docker cp <container_id>:/container/folder/with/code/files /host/empty/dir
Now stop the container. It will be deleted (--rm) when stopped.
Now if you run your original command, it will work as expected.
docker run -v /host/empty/dir:/container/folder/with/code/files -it myimage
There is another way to access the files from within the container without copying it but it's very cumbersome.

Your /host/empty/dir is always empty because the volume binding replaces (overrides) the container folder with your empty host folder. But you can not do the opposite, that is, you take a container folder to replace your host folder.
However, there is a workaround by manually copying the files from your container folder to your host folder. before using them as you have suggested.
For exemple :
run your docker image with a volume maaping between you host folder and a temp folder : docker run -v /host/empty/dir:/some-temp-folder -it myimage
copy your /container/folder/with/code/files content into /some-temp-folder to fill you host folder with you container folder
run you container with a volum mapping on /host/empty/dir but now this folder is no longer empty : run -v /host/empty/dir:/container/folder/with/code/files -it myimage
Note that steps 1 & 2 may be replaced by : Copying files from Docker container to host

Related

Is it possible to "open" vscode to see the contents of a docker container?

I have a docker image, and I am running it now (finishing with bash)
When I do, I have a file structure inside the container.
However, this is not some file structure mapped (with -v) from outside the container. These files and folders exist only inside the container.
My question is, since it is bothersome to be opening each file with vi and navigating from the terminal, is there a way that I can open vscode on these files?
Be aware that these files do not exist outside the container
I found how to do it from this link
However I used the "attach to running container" command
I rarely do that but when I have to I usually mount an empty volume to the container, then exec into the container copy the folder which I need into that empty volume, which is then replicated on my host machine. From my host machine I then open it in vscode.
However please be careful if you have sensitive information in that container, not to expose something by accident.
So the steps are:
Create empty volume ( docker-compose example )
Note do not overwrite the folder/file which you want to extract. containerpath is path which does not exist in the container prior to creating it.
volume:
- ./hostpath:/containerpath
Find docker id so that you can use it to exec into it:
docker ps
Exec into the container:
docker exec -it <container_id> /bin/sh
Copy the file/folder to that empty volume:
cp -r folder containerpath
Exit the container and look at your files in ./hostpath folder.

Is there a way to use bind mount, in docker, for a single file only

I was trying to run a simple docker container with bind mount, so the application can read and modify data.json file (from host machine). I placed data.json in /home/usr/project and ran the container with
docker container run -it -v /home/usr/project:/app container_name main.exe
project contains 3 files, rest of the 2 files were included in container build. When I try to run the container, it gives the error about the other 2 files being not found. Placing those files in /home/usr/project on local host solves the issue. Since, I want the container to only look for data.json, is there any way I can do it without keeping other 2 files unnecessarily in the bind mount directory
You can map individual files in docker
docker run -it -v /home/usr/project/data.json:/app/data.json alpine cat /app/data.json
And you can even make them readonly inside the container to avoid unwanted modifications
docker run -it -v /home/usr/project/data.json:/app/data.json:ro alpine cat /app/data.json

Docker volume bind empty volume or convert files to folders

I'm running a container by sending to docker daemon so it can run a sibling container and in that container I try to run another container and mount a volume to access some data, however in the sibling container, the volume is either empty or the file is converted to a folder...
Running the first container:
$ docker run -v /var/run/docker.sock:/var/run/docker.sock -it example /bin/bash
root#3aa35965846a:/home/node/example# ls some_volume/
test.txt
root#3aa35965846a:/home/node/example# cat some_volume/test.txt
hello
// Running the second container
root#3aa35965846a:/home/node/example# docker run -v /home/node/example/some_volume/:/some_volume/ -it node:10 /bin/bash
root#6a84739fbb92:/# ls /some_volume/
* test.txt
root#6a84739fbb92:/# cat /some_volume/test.txt/
cat: /some_volume/test.txt/: Is a directory
The first time I run the second container the volume is empty, if I try to mount a file directly it is converted to a folder, and after that if I try to mount the folder like the example above, there is only the file I tried to mount earlier and it is a folder.
How is this possible ? If i try to mount a volume outside the first container I don't have any problem, how can I fix this ?
The first path in the docker run -v option is always on the host system. For example, if you
docker run -v /etc:/x busybox cat /x/shadow
it will dump out the host's encrypted password file, regardless of whether you ran this command directly from the host or from a container.
There isn't a way to share an arbitrary directory from one container to another. If the launching container knows something about its own directory structure (in particular that some directory was mounted from a specific host path or named volume) then it can replicate that to the other container, but that's not a generic answer. The other behaviors you're seeing are just a consequence of those directories not existing on the host system.
In general I would advise not using Docker for short-lived processes that principally interact with the outside world through the filesystem. Take whatever program you'd run in the other container, install it in your image's Dockerfile, and run it directly without going through Docker.
If you really can't avoid this workflow, the only thing I've found to work reliably is to docker create the container, docker cp files in, docker start it, and docker wait for it to finish. When it's done, docker cp the result out before docker rm it. That's a kind of painstaking workflow but it gets around the problem of the two containers not sharing any filesystem space.

-v deleted all the data from the docker container

I made a docker image called myImage, there is a folder: /data I want to let the user edit it by themselves. I read that -v flag can mount the volume, so I used it like following:
I run the container with this command:
docker run -v /my_local_path:/data -it myImage /bin/bash
But surprisingly, docker cleared all the files in /data in the container. But this is not I want... I want actually the host can get all the files from /data... :(
How can I do that?
When you share a volume like this, the volume on the host overwrites the volume in the container, so the files in the container's folder will be removed.
What you need to do is put the files in the container in folder A (a folder in the container). Mount folder B (another folder in the container). Then AFTER the volume is mounted, move the files from folder A to folder B. Then these files will be both available to the host and inside the container.
You can achieve this 'move files' operation using a RUN or an ENTRYPOINT script in your Dockerfile.
See Run a script in Dockerfile
Sorry, I forget if you need RUN or ENTRYPOINT (or if either will work) but one of these will definitely do it.
I think you want ENTRYPOINT because an ENTRYPOINT script runs AFTER the container is created. Thus it will run after the volume is mounted.

Docker - access existing container files on host machine

I have a docker container which has some data in let's say /opt/files. File A and B. How can I start that container and access these files on my host machine?
I'm using Docker for Windows (Hyper-V). When i start the container with:
docker run -it -v C:/tmp:/opt/files myImage
I see an empty folder on my windows machine and inside of the container. Any new files I create there are of course reflected on both sides but how can I access files that are already in the container (e.g. because they're added in the Dockerfile)?
You can't share from inside container to host. There are two ways to do it
Copy the files from container
docker cp <containerid>:<file_path_inside_container> localpath
Share a folder other than the one where files will be generated
docker run -it -v C:/tmp:/opt/files_temp myImage
Then you get inside the container copy files from /opt/files to /opt/files_temp
Once your container is started, you can copy files inside it to your host.
Use docker cp for this (https://docs.docker.com/engine/reference/commandline/cp/).
Example : docker cp CONTAINER:SRC_PATH DEST_PATH|-

Resources