Docker data volume of container technology

Posted by Kinsbane on Mon, 25 May 2020 13:00:27 +0200

In the previous essay, we learned about docker's network related instructions. Please refer to https://www.cnblogs.com/qiuhom-1874/p/12952616.html Today, let's talk about docker's data management instructions;

In the previous blog, we emphasized that the image of docker is built hierarchically. After the image is started as a container, docker will load the read-only layer image and add a read-write layer at the top of the image. We also said that the read-write layer does not belong to the container of the image. If the container is down, then the read-write layer at the top of the image will disappear. So the problem comes, How can I save the data generated in the writable layer before the container is down? To solve this problem, let's first look at the COW mechanism of docker;

 

As shown in the figure above, the docker image is built in layers. When the data in the lowest layer has the same data in the second or higher layer, the data in the upper layer will cover the same data in the lower layer. As a result, only one copy of the same data in the upper layer and the lower layer will exist, and different data will exist. In the same way, the docker image will exist through layers For image construction, the data seen at the top level of the docker image should be the overlapping of the following layers. The same data can only be seen at the top level, while other data is composed of the superposition of different layers of data below. When running the layer container, the data seen inside the container is the result of the collection of different layers of image data and the same data. If When the container modifies an existing file during operation, the file will be copied from the bottom of the read-write layer to the read-write layer. The original file in the read-only layer still exists, but the copy of the file has been hidden by the read-write layer. This is called the docker's write time replication (cow) mechanism;

From the above information, we know that the data generated by the docker container is in the writable layer. When modifying the data, the original data will be copied from the original read-only layer to the writable layer to hide the original read-only layer, but the data in the read-only layer is still there. So after the container is deleted, the modified data will not be saved to the image, but will be deleted with the deletion of the container. Close and Restart the container will not affect the data. Is there a way to save the data in the read-write layer, even if the container is deleted, the data still exists?

First, let's talk about nfs data sharing. nfs sharing is to mount a directory to another directory through the network. When writing data to a directory, it is equivalent to writing data to a file in a remote directory. In the docker container, we call this kind of way volume. The so-called volume is one or more directories on the container. Such directories can Bypass the federated file system, and generate an association relationship with a directory on the host (binding, similar to the mount in nfs); volume will be created when the container is initialized by base The data in the volume provided by image will be copied during this period. The original intention of volume is to realize data persistence independent of the life cycle of the container, so when deleting the container, neither the volume will be deleted, nor the unreferenced volumes will be garbage collected;

Volume provides a container independent data management mechanism for docker; we can think of the image as a static file, such as a program, and compare the volume to a dynamic content, such as data, so that the image can be reused, and the volume can be shared; volume realizes the separation of program (image) and data (volume); realizes the data sharing and reuse between containers, and enables the transmission between containers Data becomes efficient and convenient; the modification of data in the data volume will take effect immediately, whether in the container or in the local operation; docker has two types of volumes, each of which has a mount point in the container, but its location on the host is different; bind mount volume is a volume that the user specifies to mount a directory on the storage to a directory inside the container. Dockekr managed volume is a volume managed by docker itself, which usually displays the ID of / var/lib/docker/vfs/dir / a volume on the host to a directory inside the container;

Example: using volume of type docker managed in the docker container of

[root@node1 ~]# docker run --name m2 -it --rm  -v /mydata linux1874/myimg:v0.1 /bin/sh  
/ # ls /
bin     dev     etc     home    mydata  proc    root    sys     tmp     usr     var
/ # cd /mydata/
/mydata # ls
/mydata # [root@node1 ~]# docker container inspect m2 -f {{.Mounts}}        
[{volume 65db95bc3010530381e2bcc20fdd216329a502527e17a1e70c1cb7f6e2d2a422 /var/lib/docker/volumes/65db95bc3010530381e2bcc20fdd216329a502527e17a1e70c1cb7f6e2d2a422/_data /mydata local  true }]
[root@node1 ~]# ll /var/lib/docker/volumes/65db95bc3010530381e2bcc20fdd216329a502527e17a1e70c1cb7f6e2d2a422/_data 
total 0
[root@node1 ~]# echo "hello world" > /var/lib/docker/volumes/65db95bc3010530381e2bcc20fdd216329a502527e17a1e70c1cb7f6e2d2a422/_data/aa.txt
[root@node1 ~]# cat /var/lib/docker/volumes/65db95bc3010530381e2bcc20fdd216329a502527e17a1e70c1cb7f6e2d2a422/_data/aa.txt
hello world
[root@node1 ~]# docker attach m2
/mydata # ls
aa.txt
/mydata # cat aa.txt 
hello world
/mydata # 

Tip: - v only specifies a directory to indicate the directory inside the specified container. It will automatically generate the mount directory on the host through docker daemon. Such a mount is called a docker managed data volume. From the above information, we can see that we can use docker container inspection - F {. Mounts}}} Container name to view the volume, identifier and mount point host directory information of the container; we create a aa.txt And then you can see the file and its contents in the container / mydata;

Test: let's stop the container to see if the data volume will be deleted?

[root@node1 ~]# cat /var/lib/docker/volumes/65db95bc3010530381e2bcc20fdd216329a502527e17a1e70c1cb7f6e2d2a422/_data/aa.txt
hello world
[root@node1 ~]# docker attach m2
/mydata # ls
aa.txt
/mydata # cat aa.txt 
hello world
/mydata # exit
[root@node1 ~]# 
[root@node1 ~]# docker ps 
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS               NAMES
33c6f135eb86        linux1874/myimg:v0.1   "/bin/sh -c '/bin/ht..."   20 minutes ago      Up 20 minutes                           m1
[root@node1 ~]# cat /var/lib/docker/volumes/65db95bc3010530381e2bcc20fdd216329a502527e17a1e70c1cb7f6e2d2a422/_data/aa.txt
cat: /var/lib/docker/volumes/65db95bc3010530381e2bcc20fdd216329a502527e17a1e70c1cb7f6e2d2a422/_data/aa.txt: No such file or directory
[root@node1 ~]#

Tip: if the -- rm option is used when running the container, but the corresponding mount point data volume will be deleted after the container is stopped;

Test: run the container without the -- rm option to see if the data volume will be deleted after the container is stopped?

[root@node1 ~]# docker run --name m2 -v /mydata -it linux1874/myimg:v0.1 /bin/sh
/ # ls /
bin     dev     etc     home    mydata  proc    root    sys     tmp     usr     var
/ # cd mydata/
/mydata # ls
/mydata # [root@node1 ~]# docker container inspect -f {{.Mounts}} m2
[{volume 28c477840d926c2fc33ebfacd607b84cfd5a272d279e1f966a65b7cb2f1d9a2e /var/lib/docker/volumes/28c477840d926c2fc33ebfacd607b84cfd5a272d279e1f966a65b7cb2f1d9a2e/_data /mydata local  true }]
[root@node1 ~]# cd /var/lib/docker/volumes/28c477840d926c2fc33ebfacd607b84cfd5a272d279e1f966a65b7cb2f1d9a2e/_data
[root@node1 _data]# ls
[root@node1 _data]# echo "hello tom" > aa.txt
[root@node1 _data]# cat aa.txt
hello tom
[root@node1 _data]# docker attach m2
/mydata # ls
aa.txt
/mydata # cat aa.txt 
hello tom
/mydata # exit
[root@node1 _data]#docker ps -a
CONTAINER ID        IMAGE                  COMMAND                  CREATED              STATUS                     PORTS               NAMES
e6560584d41e        linux1874/myimg:v0.1   "/bin/sh"                About a minute ago   Exited (0) 9 seconds ago                       m2
33c6f135eb86        linux1874/myimg:v0.1   "/bin/sh -c '/bin/ht..."   32 minutes ago       Up 32 minutes                                  m1
[root@node1 _data]# docker container rm m2
m2
[root@node1 _data]# docker ps -a
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS               NAMES
33c6f135eb86        linux1874/myimg:v0.1   "/bin/sh -c '/bin/ht..."   35 minutes ago      Up 35 minutes                           m1
[root@node1 _data]# cd 
[root@node1 ~]# cd -
/var/lib/docker/volumes/28c477840d926c2fc33ebfacd607b84cfd5a272d279e1f966a65b7cb2f1d9a2e/_data
[root@node1 _data]# ls
aa.txt
[root@node1 _data]# cat aa.txt 
hello tom
[root@node1 _data]# 

Tip: run the container without the -- rm option. Delete the container after the container stops. The data volume will not be deleted;

Example: using bind mount type volume in the docker container

[root@node1 ~]# mkdir /hostdir/v1 -p
[root@node1 ~]# docker run --name m3 -it -v /hostdir/v1/:/mydata linux1874/myimg:v0.1 /bin/sh
/ # ls /
bin     dev     etc     home    mydata  proc    root    sys     tmp     usr     var
/ # cd /mydata/
/mydata # ls
/mydata # [root@node1 ~]# docker container inspect -f {{.Mounts}} m3
[{bind  /hostdir/v1 /mydata   true rprivate}]
[root@node1 ~]# cd /hostdir/v1/
[root@node1 v1]# ls
[root@node1 v1]# echo "hello jerry" > aa.sh
[root@node1 v1]# cat aa.sh 
hello jerry
[root@node1 v1]# docker attach m3
/mydata # ls
aa.sh
/mydata # cat aa.sh 
hello jerry
/mydata # exit
[root@node1 v1]# docker ps -a
CONTAINER ID        IMAGE                  COMMAND                  CREATED              STATUS                     PORTS               NAMES
62ddbdc11a62        linux1874/myimg:v0.1   "/bin/sh"                About a minute ago   Exited (0) 4 seconds ago                       m3
33c6f135eb86        linux1874/myimg:v0.1   "/bin/sh -c '/bin/ht..."   41 minutes ago       Up 41 minutes                                  m1
[root@node1 v1]# docker container rm m3
m3
[root@node1 v1]# cd
[root@node1 ~]# cd -
/hostdir/v1
[root@node1 v1]# ls
aa.sh
[root@node1 v1]# cat aa.sh 
hello jerry
[root@node1 v1]# 

Prompt: - v specifies the host Directory: the container directory means to mount the host directory to a directory of the container; the directory in the container can be a nonexistent directory, which will be created automatically; this kind of data volume is called a bind mount type data volume; usually, the user defines the host directory as a data volume to mount to a certain directory of the container Directory; as above, we create files in the corresponding directory of the host, which can be accessed normally in the corresponding directory of the container; - v can use multiple times to specify different data volume mount relationships; usually, bind mount type volumes are used more frequently;

Example: volumes of multiple containers use the same host directory

[root@node1 ~]# ll /hostdir/v1/aa.sh 
-rw-r--r-- 1 root root 12 May 24 13:59 /hostdir/v1/aa.sh
[root@node1 ~]# cat /hostdir/v1/aa.sh
hello jerry
[root@node1 ~]#  docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@node1 ~]# docker run --name m1 -d -v /hostdir/v1/:/var/www/web/html linux1874/myimg:v0.1
9eb3287e4007f0656b1f099aac9504724307679ac41689774059388a96d75cf0
[root@node1 ~]# docker container inspect -f {{.Mounts}} m1
[{bind  /hostdir/v1 /var/www/web/html   true rprivate}]
[root@node1 ~]# docker container inspect -f {{.NetworkSettings.IPAddress}} m1      
172.17.0.2
[root@node1 ~]# curl http://172.17.0.2
<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>
<BODY><H1>404 Not Found</H1>
The requested URL was not found
</BODY></HTML>
[root@node1 ~]# curl http://172.17.0.2/aa.sh
hello jerry
[root@node1 ~]# docker run --name m2 -d -v /hostdir/v1/:/var/www/web/html linux1874/myimg:v0.1
ff877e29d10c55b355b5270218d486894958880058e2eb7bef9bdd1c7c531f0f
[root@node1 ~]# docker container inspect -f {{.Mounts}} m2
[{bind  /hostdir/v1 /var/www/web/html   true rprivate}]
[root@node1 ~]# docker container inspect -f {{.NetworkSettings.IPAddress}} m2
172.17.0.3
[root@node1 ~]# curl http://172.17.0.3
<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>
<BODY><H1>404 Not Found</H1>
The requested URL was not found
</BODY></HTML>
[root@node1 ~]# curl http://172.17.0.3/aa.sh
hello jerry
[root@node1 ~]#

Tip: attaching a data volume to a container will overwrite the original file of the container. This is not fundamentally different from mounting a mount. You can see from the above information aa.sh Put the original index.html In addition to the above methods, we can also use the -- volumes from option to specify the container from which to copy data and mount it to this container; as follows

[root@node1 ~]# docker run --name m3 -d --volumes-from m1 linux1874/myimg:v0.1
61a1fbdc9c559a594870dc1e2bbf505a4eb588fc03e5ab50233b55b907beb9b0
[root@node1 ~]# docker container inspect -f {{.Mounts}} m3
[{bind  /hostdir/v1 /var/www/web/html   true rprivate}]
[root@node1 ~]# docker container inspect -f {{.NetworkSettings.IPAddress}} m3 
172.17.0.4
[root@node1 ~]# curl http://172.17.0.4/aa.sh
hello jerry
[root@node1 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
linux1874/myimg     v0.1                e408b1c6e04f        38 hours ago        1.22MB
busybox             latest              78096d0a5478        10 days ago         1.22MB
centos              7                   b5b4d78bc90c        2 weeks ago         203MB
nginx               stable-alpine       ab94f84cc474        4 weeks ago         21.3MB
[root@node1 ~]# docker run --name c1 -it --volumes-from m1 centos:7 /bin/sh
sh-4.2# ls /
anaconda-post.log  dev  home  lib64  mnt  proc  run   srv  tmp  var
bin                etc  lib   media  opt  root  sbin  sys  usr
sh-4.2# cat /var/www/web/html/aa.sh 
hello jerry
sh-4.2#

Example: mount a data volume read-only

[root@node1 ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@node1 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
linux1874/myimg     v0.1                e408b1c6e04f        38 hours ago        1.22MB
busybox             latest              78096d0a5478        10 days ago         1.22MB
centos              7                   b5b4d78bc90c        2 weeks ago         203MB
nginx               stable-alpine       ab94f84cc474        4 weeks ago         21.3MB
[root@node1 ~]# docker run --name c1 -it -v /hostdir/v1/:/mydata:ro centos:7 /bin/sh
sh-4.2# ls /
anaconda-post.log  dev  home  lib64  mnt     opt   root  sbin  sys  usr
bin                etc  lib   media  mydata  proc  run   srv   tmp  var
sh-4.2# cd mydata/
sh-4.2# ls
aa.sh
sh-4.2# echo "hello tom" > aa.sh 
sh: aa.sh: Read-only file system
sh-4.2# exit
exit
[root@node1 ~]# docker run --name c2 -it -v /hostdir/v1/:/mydata centos:7 /bin/sh
sh-4.2# cd /mydata/
sh-4.2# ls
aa.sh
sh-4.2# echo "hello tom" > aa.sh 
sh-4.2# cat aa.sh 
hello tom
sh-4.2# exit
exit
[root@node1 ~]# 

Tip: if you do not specify the permission to mount the data volume, rw will be used by default. If you specify ro (read-only) as the permission to mount the data volume, you cannot modify the file content in the data volume inside the container;

Example: backing up data from another container with a container

[root@node1 ~]# ll /hostdir/v1/
total 4
-rw-r--r-- 1 root root 10 May 24 14:42 aa.sh
[root@node1 ~]# echo "hello world" > /hostdir/v1/bb.sh
[root@node1 ~]# echo "hello world,hello tom" > /hostdir/v1/cc.sh  
[root@node1 ~]# ls /hostdir/v1/
aa.sh  bb.sh  cc.sh
[root@node1 ~]# docker run --name m1 -d -v /hostdir/v1/:/var/www/web/html linux1874/myimg:v0.1
5959e832c01f68c24e2542138a95eb7bfeabcb7608b070ef1b536c625ddfd612
[root@node1 ~]# docker run --name c1 --volumes-from m1 -v $(pwd):/backup centos:7 tar cvf /backup/backup.tar.gz /var/www/web/html
tar: Removing leading `/' from member names
/var/www/web/html/
/var/www/web/html/aa.sh
/var/www/web/html/bb.sh
/var/www/web/html/cc.sh
[root@node1 ~]# ls
backup.tar.gz
[root@node1 ~]# tar xf backup.tar.gz 
[root@node1 ~]# ls
backup.tar.gz  var
[root@node1 ~]# cd var/www/web/html/
[root@node1 html]# ls
aa.sh  bb.sh  cc.sh
[root@node1 html]# cat aa.sh bb.sh cc.sh 
hello tom
hello world
hello world,hello tom
[root@node1 html]# 

Tip: explain that the container is used to back up the data in another container. First, clone the data volume of m1 through -- volumes from, then mount the current path to the / backup directory inside the container through - v, and then execute tar CVF / backup by starting the container/ backup.tar.gz /var/www/web/html to package / var/www/web/html files in the container into / backup/backup.tar.gz The reason why we can see the packed files in the current directory is because we mount the current path to the / backup directory in the container, so we can see the packed files in the current host directory;

Example: using a container to recover the data file just packaged

Run a container first

[root@node1 ~]# docker ps -a
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS               NAMES
5959e832c01f        linux1874/myimg:v0.1   "/bin/sh -c '/bin/ht..."   15 minutes ago      Up 15 minutes                           m1
[root@node1 ~]# docker run --name m2 -it -v /var/www/web/html linux1874/myimg:v0.1 /bin/sh
/ # ls /var/www/web/html/
index.html
/ # [root@node1 ~]#

Then, the data volume of the container before the container cloning is performed. The current directory is mounted as the data volume, and the tar xf command is executed to unpack

[root@node1 ~]# docker ps -a
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS               NAMES
6462f22e0d7f        linux1874/myimg:v0.1   "/bin/sh"                2 minutes ago       Up 2 minutes                            m2
5959e832c01f        linux1874/myimg:v0.1   "/bin/sh -c '/bin/ht..."   22 minutes ago      Up 21 minutes                           m1
[root@node1 ~]# docker run --name c2 --volumes-from m2 -v $(pwd):/backup centos:7 tar xf /backup/backup.tar.gz
[root@node1 ~]# docker attach m2
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # ls /var/www/web/html/
aa.sh       bb.sh       cc.sh       index.html
/ # cd /var/www/web/html/
/var/www/web/html # cat aa.sh bb.sh cc.sh 
hello tom
hello world
hello world,hello tom
/var/www/web/html # 

Tip: the idea of the above command is to run container c2 Clone the m2 data volume to c2 first, then mount the current host directory to the container's / backup, and then perform the unpacking operation; note also that if the container's working directory is not the root directory or other special directory, the unpacking command can specify the directory to which to unpack through - C;

Topics: Linux Docker CentOS curl network