-v deleted all the data from the docker container - docker

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.

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.

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.

Docker mount volume to reflect container files in host

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

docker mount data from container to host

I created own Dockerfile, during building I inserted to /opt/wilfly/log my log4j.xml.
Now I need create volume /mnt/data/logs/application:/opt/wildfly/log
I run command
sudo docker run --name=myapp -v /mnt/data/logs/application:/opt/wildfly/log -d -i -t application
But when I look in docker container, folder /opt/wilfly/log is empty. In this folder should by log4j.xml.
Thank you.
Maybe you should move it into another directory.
For example move log4j.xml to /opt/wilfly/ and set logging path to /opt/wilfly/log.
When you run the container, log4j.xml will not disappear.
When you mount the data, the folder from your host "override" your mounted folder within the container.
Thus, there are some options you can do:
copy the log4j.xml into your local /mnt/data/logs/application folder and run the container as you did.
remove the -v /mnt/data/logs/application:/opt/wildfly/log and use the original log4j.xml that you were added during the image build.
Please note that you can also mount only the file if you like (rather than the entire floder): -v /mnt/data/logs/application/log4j.xml:/opt/wildfly/log/log4j.xml but it won't change the behavior - the file from your host will be mounted into the container and not in the opposite direction.

Docker add files to VOLUME

I have a Dockerfile which copies some files into the container and after that creates a VOLUME.
...
ADD src/ /var/www/html/
VOLUME /var/www/html/files
...
In the src folder is an files folder and in this files folder are some files I need to have copied to the VOLUME the first time the container gets started.
I thought the first time the container gets created it uses the content of the original dir specified in the volume but this is not the case.
So how can I get the files into this folder?
Do I need to create an extra folder and copy it with a runscript (I hope not)?
Whatever you put in your Dockerfile is just evaluated at build time (and not when you are creating a new container).
If you want to make file from the host available in your container use a data volume:
docker run -v /host_dir:/container_dir ...
In case you just want to copy files from the host to a container as a one-off operation you can use:
docker cp /host_dir mycontainer:/container_dir
The issue is with your ADD statement. Also you might not understand how volumes are accessed. Compare your efforts with the demo below:
FROM alpine #, or your favorite tiny image
ADD src/files /var/www/html/files
VOLUME /var/www/html/files
Build an image called 'dataimg':
docker build -t dataimg .
Use the dataimg image to create a data container named 'datacon':
docker run --name datacon dataimg /bin/cat
Mount the volume from datacon in your nginx container:
docker run --volumes-from datacon nginx ls -la /var/www/html/files
And you'll see the listing of /var/www/html/files reflects the contents of src/files

Resources