First create a volume sample_vol
docker volume create sample_vol
My Dockerfile
FROM archlinux/base
RUN touch /root/testing [**edited** find note at RUN below]
# VOLUME sample_vol:/root [**edited** this will not work, because VOLUME will not accpet named volumes. So this will not mount at /root, it will mount at sample_vol:/root which does not exist]
VOLUME "/root" or VOLUME ["/root"] [**edited** this will create a local mount volume only till the time the container is running. I tried to use named volumes like VOLUME ["name:/root"] but didnt work ]
# RUN touch /root/testing [**edited** this will not work because volume when mounted will only copy files till it got declared]
build the image
docker build -t archlinux/sample_vol .
checking whether testing file is created in sample_vol
docker run --rm -it -v=sample_vol:/tmp/myvolume archlinux/base ls /tmp/myvolume
It does not show any file testing created
while
$ docker run --rm -it --name sample_vol archlinux/sample_vol ls /root/testing
It shows the file testing is created in the /root/ of build image
So why sample_vol is not mounted at /root and testing is created inside it.
Update: Reason i found can be due to
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#volume
Changing the volume from within the Dockerfile: If any build steps
change the data within the volume after it has been declared, those
changes will be discarded.
You are misunderstanding docker-volume.
Docker-Image are more about build time.
Docker-Volume is useful only in runtime.
Try running following commands to get an idea:
docker run --rm -it -v=sample_vol:/tmp/myvolume archlinux/base touch /tmp/myvolume/1.txt
docker run --rm -it -v=sample_vol:/tmp/myvolume archlinux/base touch /tmp/myvolume/2.txt
docker run --rm -it -v=sample_vol:/tmp/myvolume archlinux/base touch /tmp/myvolume/3.txt
docker run --rm -it -v=sample_vol:/tmp/myvolume archlinux/base ls -altr /tmp/myvolume/
1st container create a file 1.txt in docker volume mounted at /tmp/myvolume and then container gets deleted after this operation.
2nd container create a file 2.txt in docker volume mounted at /tmp/myvolume and then container gets deleted after this operation.
3rd container create a file 3.txt in docker volume mounted at /tmp/myvolume and then container gets deleted after this operation.
4th container list files in docker volume mounted at /tmp/myvolume and then container gets deleted after this operation.
Docker volume is to store persistent data outside of the lifecycle of container.That means when you remove container , you still have data outside of the container living inside volume.
So next time if you create a container and attach that docker volume - you will automatically get all the data with new container.
Consider an example of database image where you want to have data in volume so that when you change the container to the higher version - you will get the old data in the new database.
I was using Docker in the old way, with a volume container:
docker run -d --name jenkins-data jenkins:tag echo "data-only container for Jenkins"
But now I changed to the new way by creating a named volume:
docker volume create --name my-jenkins-volume
I bound this new volume to a new Jenkins container.
The only thing I've left is a folder in which I have the /var/jenkins_home of my previous jenkins container. (by using docker cp)
Now I want to fill my new named volume with the content of that folder.
Can I just copy the content of that folder to /var/lib/jenkins/volume/my-jenkins-volume/_data?
You can certainly copy data directly into /var/lib/docker/volumes/my-jenkins-volume/_data, but by doing this you are:
Relying on physical access to the docker host. This technique won't work if you're interacting with a remote docker api.
Relying on a particular aspect of the volume implementation would could change in the future, breaking any processes you have that rely on it.
I think you are better off relying on things you can accomplish using the docker api, via the command line client. The easiest solution is probably just to use a helper container, something like:
docker run -v my-jenkins-volume:/data --name helper busybox true
docker cp . helper:/data
docker rm helper
You don't need to start some container to add data to already existing named volume, just create a container and copy data there:
docker container create --name temp -v my-jenkins-volume:/data busybox
docker cp . temp:/data
docker rm temp
You can reduce the accepted answer to one line using, e.g.
docker run --rm -v `pwd`:/src -v my-jenkins-volume:/data busybox cp -r /src /data
Here are steps for copying contents of ~/data to docker volume named my-vol
Step 1. Attach the volume to a "temporary" container. For that run in terminal this command :
docker run --rm -it --name alpine --mount type=volume,source=my-vol,target=/data alpine
Step 2. Copy contents of ~/data into my-vol . For that run this commands in new terminal window :
cd ~/data
docker cp . alpine:/data
This will copy contents of ~/data into my-vol volume. After copy exit the temporary container.
You can add this BASH function to your .bashrc to copy files to a existing Docker volume without running a container
# Usage: copy-to-docker-volume SRC_PATH DEST_VOLUME_NAME [DEST_PATH]
copy-to-docker-volume() {
SRC_PATH=$1
DEST_VOLUME_NAME=$2
DEST_PATH="${3:-}"
# create smallest Docker image possible
echo -e 'FROM scratch\nLABEL empty=""' | docker build -t empty -
# create temporary container to be able to mount volume
CONTAINER_ID=$(docker container create -v my-volume:/data empty cmd)
# copy files to volume
docker cp "${SRC_PATH}" "${CONTAINER_ID}":"/data/${DEST_PATH}"
# remove temporary container
docker rm "${CONTAINER_ID}"
}
Example
# create volume as destination
docker volume create my-volume
# create directory to copy
mkdir my-dir
echo "hello file1" > my-dir/my-file-1
# copy directory to volume
copy-to-docker-volume my-dir my-volume
# list directory on volume
docker run --rm -it -v my-volume:/data busybox ls -la /data/my-dir
# show file content on volume
docker run --rm -it -v my-volume:/data busybox cat /data/my-dir/my-file-1
# create another file to copy
echo "hello file2" > my-file-2
# copy file to directory on volume
copy-to-docker-volume my-file-2 my-volume my-dir
# list (updated) directory on volume
docker run --rm -it -v my-volume:/data busybox ls -la /data/my-dir
# check volume content
docker run --rm -it -v my-volume:/data busybox cat /data/my-dir/my-file-2
If you don't want to create a docker and you can access as privileged user to , simply do (on Linux systems):
docker volume create my_named_volume
sudo cp -p . /var/lib/docker/volumes/my_named_volume/_data/
Furthermore, it also allows you to access data in docker runtime or also with docker containers stopped.
If you don't want to create a temp helper container on windows docker desktop (backed by wsl2) then
copy the files to below location
\\wsl$\docker-desktop-data\version-pack-data\community\docker\volumes\my-volume\_data
here my-volume is the name of your named volume. browse the above path from address bar in your file explorer. This is a internal network created by wsl in windows.
Note: it might be better to use docker API like mentioned by larsks, but I have not faced any issues on windows.
Similarly on linux files can be copied to
/var/lib/docker/volumes/my-volume/_data/
https://docs.docker.com/engine/userguide/dockervolumes/ says:
"Volumes are initialized when a container is created. If the container’s base image contains data at the specified mount point, that existing data is copied into the new volume upon volume initialization."
However this is not exactly what I'm observing. Here's my scenario:
I create a container that contains some data in /opt/data
I commit this container and create an image out of it
I create another container using the image I've just prepared and create a volume that points /opt/data to a local catalog.
According to the docs, I expected that files under /opt/data of the image will be copied to the locally created volume. It's not happening..
<local>:~$ docker run --name test -it ubuntu bash
root#76f42fce6ab7:/# mkdir /opt/data
root#76f42fce6ab7:/# echo "foo" > /opt/data/my-data
$ docker commit test test-with-data
<local>:~$ docker run -it -v /tmp/test-volume:/opt/data test-with-data bash
root#731b483527ad:/# ls /opt/data
root#731b483527ad:/#
root#731b483527ad:/# exit
Is there something I don't understand here?
It's because you've specified a host directory. If you don't specify a host directory and instead let Docker manage the volume, it works as you expect:
$ docker run --name test -it debian bash
root#ac99b805a689:/# mkdir /opt/data
root#ac99b805a689:/# echo "foo" > /opt/data/my-data
root#ac99b805a689:/# exit
exit
$ docker commit test test-with-data
a35463157fbee6180ed91c458288cf528da93a23bf340f44c3d2a7ff355fa2b1
$ docker run -it -v /opt/data/ test-with-data bash
root#73f70c3b5518:/# ls /opt/data
my-data
root#73f70c3b5518:/# cat /opt/data/my-data
foo
I have running docker container and I want to commit the changes on that container, but the size of one of the directories is very huge and I want to exclude it from the snapshot.
How to commit changes on that container while excluding a directory from that image?
Container's volumes won't be saved when you commit a container as an image. So you can take advanced of this to exclude a folder (volume) from the snapshot. For example, suppose you want to exclude dir /my-videos from your image when committing. You can run your container mounting /my-videos as a volume:
docker run -i -t -v /my-videos my_container /bin/bash
or you mount a host's folder in container's /my-videos:
docker run -i -t -v /home/user/videos:/my-videos my_container /bin/bash
when i try to mount a host directory as data volume in docker its not mount any directory to docker container(image).
When i run
sudo docker run -t -i --name web -v /home/rponna/src/webapp:/opt/webapp ramnathreddy
it returns container id
7dcc03c397d56514015220a073c9e951478bf84aceb90b880bb93a5716079212
But when i run that container it will not show any files in opt/webapp (its empty).