Volumes#
You have to use -v
option of the docker run
command to mount volume to container. In general you have to use following syntax:
docker run \
-v <volume1>:<path in container1> \
-v <volume2>:<path in container2> \
...
Sometimes it’s extremely useful to mount a specific folder but not a volume; you need to use folder name instead of volume name
- this case is specific type of the volume and called bind mount.
Mount to container#
To mount volume to the container you have to use -v <volume name>:<path in container>
option.
The following example creates a Docker container that mounts test_volume
as folder
and stores my_file
with my message
.
docker volume create test_volume &> /dev/null
docker run --rm -itd\
--name test_container \
-v test_volume:/folder alpine \
sh -c "echo \"my message\" > /folder/my_file" &> /dev/null
sleep 3
After while that container stops and being removed. So there aren’t any containers yet.
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
But data has been saved. We can show this by mounting the same volume as the temp
folder. If we now check the files stored in temp
- there will be my_file
.
docker run --rm -it -v test_volume:/temp alpine ls temp
my_file
And it’ll store exactly the same content that we saved at the begining.
docker run --rm -it -v test_volume:/temp alpine cat /temp/my_file
my message
Don’t forget to remove test volume after all.
docker volume rm test_volume
test_volume
Bind mount#
Bind mount is a specific but extremely usefull type of volume. It’s a folder on the host specified by user to be mounted to the container.
In the following example creted folder temp_folder
, mounted to container as temp_folder_inc_count
folder.
Note here is specified --user $(id -u):$(id -g)
to run container with same user notebook runned. It’ll garantee that commands in host will have full rights for modifying/deleting files created from container.
mkdir temp_folder
docker run \
--user $(id -u):$(id -g) \
-v $(pwd)/temp_folder:/temp_folder_in_cont \
--rm -itd --name temp_example \
ubuntu &> /dev/null
Now temp_folder
on the host and temp_folder_in_count
on the container are the same folders. So the file container_file
created by the container will be accessible from the host and vice versa the file host_file
created by the host will be accessible from the container.
docker exec temp_example \
bash -c "echo \'hello from container\' >> temp_folder_in_cont/container_file"
echo "hello from host" >> temp_folder/host_file
Now let us check conatiner_file
from host and host_file
from container.
cat temp_folder/container_file
docker exec temp_example cat temp_folder_in_cont/host_file
'hello from container'
hello from host
Finally, don’t forget to clean the system of debris.
docker stop temp_example &> /dev/null
rm -r temp_folder
Read only mount#
By adding :ro
to the path of the folder in container you can make it to be read only in the container.
In the following example we creating file ro_ex
which have content original_data
and mount that file to the container.
echo "original data" > ro_ex
docker run --rm -idt --name ro_ex \
-v $(pwd)/ro_ex:/experimental/ro_ex:ro \
ubuntu &> /dev/null
Now let us try to read and modify this file from the container.
docker exec ro_ex cat /experimental/ro_ex
docker exec ro_ex bash -c "echo \"modified data\" > /experimental/ro_ex"
original data
bash: line 1: /experimental/ro_ex: Read-only file system
So there is no problem reading the file, but the attempt to modify it was rejected.
The next cell confirms that you can keep the file unchanged.
cat ro_ex
original data
Keeping your system clean.
docker stop ro_ex &> /dev/null
rm -r ro_ex
Mounting .dockerignore
files#
Even if you mount the file described in .dockerignore, we will still have it in the container.
In the following example, I create app/ignore_file.txt
and mention it in dockerignore. Build image using this .dockerignore, but in container based on this image I mount app
folder. And as a result I can see contents of ignore_file.txt
regardless of what I specified in the .dockerignore
.
%%bash
cd filesystem_example
mkdir app
echo "message in ignore_file.txt" > app/ignore_file.txt
echo "=====.dockerignore====="
echo "app/ignore_file.txt" > .dockerignore
cat .dockerignore
echo "=====dockerfile====="
echo "FROM ubuntu" > dockerfile
cat dockerfile
# build image with setted .dockerignore
docker build -t test_image &> /dev/null
# start container mountig file mentioned in .dockerignore
docker run --rm -itd --name ignore_ex\
-v $(pwd)/app:/app\
ubuntu &> /dev/null
echo "=====ignore-file from container====="
# make sure that this secret file is in the container
docker exec ignore_ex cat app/ignore_file.txt
docker stop ignore_ex &> /dev/null
docker rmi test_image &> /dev/null
rm -r app
rm .dockerignore
rm dockerfile
=====.dockerignore=====
app/ignore_file.txt
=====dockerfile=====
FROM ubuntu
=====ignore-file from container=====
message in ignore_file.txt
Volume by default#
Some containers create their own volumes by default when they run, so you may find that your entire hard drive is flooded.
For example yandex/clickhouse-server
. Let’s list volumes available in your system.
docker volume ls
DRIVER VOLUME NAME
Now run 3 clickhouse servers.
docker run -d --name db_1 --rm yandex/clickhouse-server &> /dev/null
docker run -d --name db_2 --rm yandex/clickhouse-server &> /dev/null
docker run -d --name db_3 --rm yandex/clickhouse-server &> /dev/null
There are 3 more new volumes.
docker volume ls
docker stop db_1 db_2 db_3 &> /dev/null
DRIVER VOLUME NAME
local 2a663bcb67e10d518c9380ef736c2b3a2a2cdbc0762e75c1e0ade4692a211140
local 7bc74bac7549fda3ad02caee85febd8161c6c2072e7626464f87fc63cef0234d
local 49d77d54fa7a358281c696412d5fc9ef87d7c3e9acb12fe449befb72c9faf9df
So clickhouse creates volume for each new container.
Several volumes#
You can repeat -v
option in docker run
many times as you need.
Here is an example where we add multiple volumes to a Docker container.
Note that we specify the -u $(id -u):$(id -g)
option to be able to work with files created in the container from the host.
mkdir dir1 dir2
docker run --rm -itd \
-u $(id -u):$(id -g) \
-v $(pwd)/dir1:/dir1 \
-v $(pwd)/dir2:/dir2 \
--name test_container \
alpine
06634a5fcefb4dd7298c139e45b1d5f3cb031c9da2642f3f407dad1205e91a70
Now to be sure that everything is fine lets manipulate with created folders from containers.
docker exec test_container sh -c "echo \"message\" > /dir1/file_for_dir1"
docker exec test_container sh -c "echo \"message\" > /dir2/file_for_dir2"
And check that our manipulations are reflected on the host file system.
ls dir1
ls dir2
file_for_dir1
file_for_dir2
Finally don’t forget to clear cache from the system.
docker stop test_container
rm -r dir1 dir2
test_container