Docker volumes and bind-mounts
Whenever a running container wants to persist data, it actually put that data into the writable layer through storage driver.
Let's use our nginx2
container created previously.
Tip
If you don't have this container running you can recreate it with the following command:
docker container run -d -p 80:80 --name nginx2 nginx
Let’s use the docker exec
command to edit the welcome page and load it.
docker container exec -it nginx2 bash
echo "I changed the content of this file inside the running container..." > /usr/share/nginx/html/index.html
You will be able to see these changes connecting to the port 80 of your host:
Let’s restart the container. What happens? We can still see the changes that we made.
Now..what if we stop this container and start another one and load the page?
docker container run -d -p 8080:80 --name nginx3 nginx
Warning
For this second container you need to specify a different host port, otherwise there will be a conflict and your container will not be started:
driver failed programming external connectivity on endpoint nginx3 (96fad8e096e1a124147049765f0d734e2a034712fb253711450c62a7158b1f21): Bind for 0.0.0.0:80 failed: port is already allocated.
Connect to port 8080 of your host, you will see the default welcome page: there is no way that we could access the file that we have changed in another container.
Using docker volumes¶
Let's create our first docker volume:
docker volume create myvol
We can list the volumes with:
docker volume ls
DRIVER VOLUME NAME
local myvol
We can see the location of volumes in the docker area of the host file system with the inspect command:
docker volume inspect myvol
[
{
"CreatedAt": "2021-06-07T10:53:26Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/myvol/_data",
"Name": "myvol",
"Options": {},
"Scope": "local"
}
]
Let's re-create our nginx
container with the following command that mounts the volume myvol
in /usr/share/nginx/html
:
Remove the old container
docker container rm -f nginx3
Recreate it with the volume mounted:
docker container run -d -p 8080:80 --name nginx3 --mount type=volume,source=myvol,destination=/usr/share/nginx/html nginx
Note
- if we didn’t create the volume earlier docker will create it for us with the name given in source field of
--mount
parameter - volumes by default will not be deleted while we removing the container
- if the container has got in
target
directory any files, this files will be copied into the volume
Enter the container and modify the welcome page:
docker exec -it nginx3 bash
Once inside the container, run the following command:
echo "I've changed the content of this file in the docker volume" > /usr/share/nginx/html/index.html
Let' stop and remove this container and create a new one with the same command:
docker rm -f nginx3
docker container run -d -p 8080:80 --name nginx3 --mount type=volume,source=myvol,destination=/usr/share/nginx/html nginx
If we load the page again we will still see the html file that we edited in the volume.
Using bind mounts¶
Note
- if we didn’t create a directory on docker host earlier docker will not create it for us with
--mount
parameter, auto-creating is available only in older--volume
- bind mounts by default will not be deleted while removing the container
- if the container has got in
target
directory any files, this files will NOT be copied into bind mount directory, bind directory will cover any files in a target container directory
Try the following command:
docker container run -d -p 8088:80 --name nginx4 --mount type=bind,source=/tmp/nginx,destination=/usr/share/nginx/html nginx
You will get an error since the path /tmp/nginx
does not exist:
docker: Error response from daemon: invalid mount config for type "bind": bind source path does not exist: /tmp/nginx.
See 'docker run --help'.
Let's create the directory on the host:
mkdir /tmp/nginx
Now re-run the command for creating the container:
docker container run -d -p 8088:80 --name nginx4 --mount type=bind,source=/tmp/nginx,destination=/usr/share/nginx/html nginx
If you inspect the container you will see the bind-mount:
docker container inspect nginx4
...
"Mounts": [
{
"Type": "bind",
"Source": "/tmp/nginx",
"Target": "/usr/share/nginx/html"
}
],
...
Connect to port 8088
on the host IP to see the result:
As you can see we get an error message from nginx as the bind-mount has overwritten the content of /usr/share/nginx/html
(Remember that the behaviour with docker volumes is different, any file inside the container is copied in the volume)
Let's create the index.html
file in the host path /tmp/nginx
:
echo "I've changed the content of this file on the host" > /tmp/nginx/index.html
Then reload the page in the browser:
Question
As done before, try to remove the container and recreate it with the same bind-mount...what happens?