天天看点

Docker - Docker数据持久化

Docker - Docker数据持久化

Docker的数据持久化主要有两种方式:

  1. Bind Mount。
  2. Volume。

Docker的数据持久化,即是数据不随着容器的结束而结束,数据存储于宿主机上,要么存储于宿主机某个指定目录中(使用Bind Mount),要么存储于Docker管理的Volume中(​

​/var/lib/docker/volumes​

​下)。

Bind Mount在Docker早期便开始使用了,用于将宿主机中的目录挂载(​

​mount​

​​)到容器中。但是当Bind Mount在不同的宿主机系统时,它是不可移植的,比如Windows和Linux的目录结构是不一样的,Bind Mount所指向的宿主机目录也不能一样。这也是为什么Bind Mount不能出现在​

​Dockerfile​

​​中的原因,因为这样​

​Dockerfile​

​就不可移植了。

Bind Mount有几点需要注意:

  • 宿主机的目录路径必须为全路径(准确的说需要以​

    ​/​

    ​​或​

    ​~/​

    ​开始的路径),不然Docker会将其当做Volume而不是Bind Mount处理。
  • 如果宿主机上的目录不存在,Docker会自动创建该目录。
  • 如果容器中的目录不存在,Docker会自动创建该目录。
  • 宿主机目录无论有没文件,都会覆盖容器挂载的目录。

Volume也是绕过容器的文件系统,直接将数据存储到宿主机上,只是Volume是被Docker管理的,Docker下所有的Volume都在宿主机上的指定目录下​

​/var/lib/docker/volumes​

​。

还有需要注意的是:

  • Bind Mount:容器挂载的目录以宿主机目录为准,无论宿主机目录有无文件,都会覆盖容器挂载的目录。
  • Volume:宿主机目录有文件时,以宿主机目录为准;宿主机目录没有文件时,从容器挂载的目录复制过来,再以宿主机目录为准。

挂载数据卷(Volume)

在镜像​

​centos:7​

​​上创建容器,并且将容器命名为​

​centos.7.5​

​​,通过​

​-v​

​​选项可以给容器添加数据卷;启动之后,到容器内部可以看到数据卷的​

​Destination​

​​是​

​centos-volume​

​​(由​

​-v​

​​选项后面的参数指定),在​

​centos-volume​

​​中创建文件​

​hello_kaven​

​。

[root@izoq008ryseuupz docker]# docker run -it --name centos.7.5 -v centos-volume centos:7  
[root@e2a5901b29b2 /]# ll
total 60
-rw-r--r--  1 root root 12114 Nov 13 01:55 anaconda-post.log
lrwxrwxrwx  1 root root     7 Nov 13 01:53 bin -> usr/bin
drwxr-xr-x  2 root root  4096 Nov 25 09:36 centos-volume
drwxr-xr-x  5 root root   360 Nov 25 09:36 dev
drwxr-xr-x  1 root root  4096 Nov 25 09:36 etc
drwxr-xr-x  2 root root  4096 Apr 11  2018 home
lrwxrwxrwx  1 root root     7 Nov 13 01:53 lib -> usr/lib
lrwxrwxrwx  1 root root     9 Nov 13 01:53 lib64 -> usr/lib64
drwxr-xr-x  2 root root  4096 Apr 11  2018 media
drwxr-xr-x  2 root root  4096 Apr 11  2018 mnt
drwxr-xr-x  2 root root  4096 Apr 11  2018 opt
dr-xr-xr-x 92 root root     0 Nov 25 09:36 proc
dr-xr-x---  2 root root  4096 Nov 13 01:55 root
drwxr-xr-x 11 root root  4096 Nov 13 01:55 run
lrwxrwxrwx  1 root root     8 Nov 13 01:53 sbin -> usr/sbin
drwxr-xr-x  2 root root  4096 Apr 11  2018 srv
dr-xr-xr-x 13 root root     0 Apr 11  2018 sys
drwxrwxrwt  7 root root  4096 Nov 13 01:55 tmp
drwxr-xr-x 13 root root  4096 Nov 13 01:53 usr
drwxr-xr-x 18 root root  4096 Nov 13 01:54 var
[root@e2a5901b29b2 /]# cd centos-volume
[root@e2a5901b29b2 centos-volume]# ll
total 0
[root@e2a5901b29b2 centos-volume]# echo "hello kaven" > hello_kaven
[root@e2a5901b29b2 centos-volume]# ll
total 4
-rw-r--r-- 1 root root   12 Nov 25 09:39 hello_kaven
[root@e2a5901b29b2 centos-volume]# cat hello_kaven
hello kaven      

容器是否成功挂载到数据卷,可以通过查看容器信息来获取,运行下面的命令即可。

docker inspect centos.7.5      

得到的信息中有下面这一段。

"Mounts": [
            {
                "Type": "volume",
                "Name": "c8079a1f169f2f0d93923db7b785f1033a46bdc8cf6baf73d742ebbb3c03d6a4",
                "Source": "/var/lib/docker/volumes/c8079a1f169f2f0d93923db7b785f1033a46bdc8cf6baf73d742ebbb3c03d6a4/_data",
                "Destination": "centos-volume",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ]      

类型是​

​volume​

​​,​

​/var/lib/docker/volumes/c8079a1f169f2f0d93923db7b785f1033a46bdc8cf6baf73d742ebbb3c03d6a4/_data​

​​就是数据卷在宿主机中的目录路径,通过​

​docker volume ls​

​​命令,也可以查询到数据卷名称为​

​c8079a1f169f2f0d93923db7b785f1033a46bdc8cf6baf73d742ebbb3c03d6a4​

​的数据卷。

[root@izoq008ryseuupz docker]# docker volume ls
DRIVER              VOLUME NAME
local               3c1ed533ce142b49eadc15ba57b87a3bac780e89e22c06503b3e909ab69ed62f
local               5b086d5fdb68b5a58593fdca6d6f0a9b3ead0ed929fd3961b7db48e3a928c24d
local               6b5a0394e690c4e0e869ddecc0db24a748a0229c70a83db46e0f2f95e3314958
local               8eb0f149b72711acd9618f827fc26a9afcce63ed51f1e60ac48e752344f88f22
local               08b4d10ef219075ee8a283112be06e1df52729bf23d3216342da3f8b21a0c127
local               31a6cbc600b3d30d0c567b3842ce5e7944495fcc12d42008385912d32facfd7a
local               208ddc66938b611237d4e868cb8800a36b5390969ba7a22d2d2e65a8c173b2c8
local               3285a7fb977eb7a87da83b2a5ff838c98037b15ec659eeff68c489e7004114ea
local               a4beb8e0e17a3369c8c9a447d777323df71d2b5e2f77ebfc69cc99af39e1077a
local               c8079a1f169f2f0d93923db7b785f1033a46bdc8cf6baf73d742ebbb3c03d6a4
local               centos-volume
local               db153ec29b07b6268e7204fc2e91a32db91797bcd8f4d92c7e2637577cd1a155
local               dcf0505225e08c4c4d24f0e89ac83ed02a5387620734c4add6ab4f1d8196489c
local               f00edae7bd06b264a25329143fa2207e998491e459c24b0c30b1f78996a49369
[root@izoq008ryseuupz docker]# cd volumes
[root@izoq008ryseuupz volumes]# pwd
/var/lib/docker/volumes
[root@izoq008ryseuupz volumes]# cd c8079a1f169f2f0d93923db7b785f1033a46bdc8cf6baf73d742ebbb3c03d6a4
[root@izoq008ryseuupz c8079a1f169f2f0d93923db7b785f1033a46bdc8cf6baf73d742ebbb3c03d6a4]# ll
total 4
drwxr-xr-x 3 root root 4096 Nov 25 17:39 _data
[root@izoq008ryseuupz c8079a1f169f2f0d93923db7b785f1033a46bdc8cf6baf73d742ebbb3c03d6a4]# cd _data
[root@izoq008ryseuupz _data]# ll
total 4
-rw-r--r-- 1 root root   12 Nov 25 17:39 hello_kaven
[root@izoq008ryseuupz _data]# cat hello_kaven
hello kaven      

很显然,容器到宿主机之间的数据共享已经实现了。那宿主机到容器呢?当然也是可以的。

[root@izoq008ryseuupz _data]# echo "this is new file" > newFile
[root@izoq008ryseuupz _data]# ll
total 8
-rw-r--r-- 1 root root   12 Nov 25 17:39 hello_kaven
-rw-r--r-- 1 root root   17 Nov 25 18:08 newFile
[root@izoq008ryseuupz _data]# docker start -i centos.7.5
[root@e2a5901b29b2 /]# cd centos-volume
[root@e2a5901b29b2 centos-volume]# ll
total 8
-rw-r--r-- 1 root root   12 Nov 25 09:39 hello_kaven
-rw-r--r-- 1 root root   17 Nov 25 10:08 newFile
[root@e2a5901b29b2 centos-volume]# cat newFile
this is new file      

Bind Mount

将容器目录​

​/shared_volume​

​​挂载到宿主机目录​

​/var/lib/docker/volumes/shared_volume​

​。

docker run -it --name centos.share1 -v /var/lib/docker/volumes/shared_volume:/shared_volume  centos:7      

在容器挂载目录中创建文件​

​share​

​,在宿主机挂载目录中也可以访问到。

[root@izoq008ryseuupz volume]# cd /var/lib/docker/volumes/shared_volume
[root@izoq008ryseuupz shared_volume]# pwd
/var/lib/docker/volumes/shared_volume
[root@izoq008ryseuupz shared_volume]# docker run -it --name centos.share1 -v /var/lib/docker/volumes/shared_volume:/shared_volume  centos:7
[root@1065ceefb3da /]# ls
anaconda-post.log  bin  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  shared_volume  srv  sys  tmp  usr  var
[root@1065ceefb3da /]# cd shared_volume 
[root@1065ceefb3da shared_volume]# echo "this is share" > share 
[root@1065ceefb3da shared_volume]# ls
share
[root@1065ceefb3da shared_volume]# exit
exit
[root@izoq008ryseuupz shared_volume]# ls
share
[root@izoq008ryseuupz shared_volume]# cat share
this is share      

当然反过来也可以。

[root@izoq008ryseuupz ~]# cd /var/lib/docker/volumes/shared_volume
[root@izoq008ryseuupz shared_volume]# ll
total 4
-rw-r--r-- 1 root root   14 Nov 25 21:19 share
[root@izoq008ryseuupz shared_volume]# mkdir share2
[root@izoq008ryseuupz shared_volume]# ll
total 8
-rw-r--r-- 1 root root   14 Nov 25 21:19 share
drwxr-xr-x 2 root root 4096 Nov 27 12:26 share2
[root@izoq008ryseuupz shared_volume]# docker start -i centos.share1
[root@1065ceefb3da /]# cd shared_volume
[root@1065ceefb3da shared_volume]# ll
total 8
-rw-r--r-- 1 root root   14 Nov 25 13:19 share
drwxr-xr-x 2 root root 4096 Nov 27 04:26 share2      

查看容器信息。

docker inspect centos.share1      

通过下面的信息可以知道容器已经成功挂载了宿主机目录。

"Mounts": [
            {
                "Type": "bind",
                "Source": "/var/lib/docker/volumes/shared_volume",
                "Destination": "/shared_volume",
                "Mode": "",
                "RW": true,
                "Propagation": "rslave"
            }
        ]      

类型是​

​bind​

​。

挂载指定数据卷(Volume)

不需要自己去创建数据卷,通过下面这条命令可以让Docker去创建数据卷​

​kaven_volume​

​。

docker run -itd --name kaven -v kaven_volume:/kaven/volume centos:7      

容器​

​kaven​

​成功运行起来了。

[root@izoq008ryseuupz ~]# docker run -itd --name kaven -v kaven_volume:/kaven/volume centos:7
97bff81a64bfd63d12e931705ae3bbb8266f6f53a8612fe965f37e0ce53d6c96
[root@izoq008ryseuupz ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
97bff81a64bf        centos:7            "/bin/bash"         3 seconds ago       Up 3 seconds                                 kaven      

查看容器信息。

docker inspect kaven      

通过下面的信息可以知道容器已经成功挂载了数据卷。

"Mounts": [
            {
                "Type": "volume",
                "Name": "kaven_volume",
                "Source": "/var/lib/docker/volumes/kaven_volume/_data",
                "Destination": "/kaven/volume",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ]      

类型是​

​volume​

​。

挂载其他容器的数据卷

比如挂载容器​

​kaven​

​的数据卷。

docker inspect kaven      
"Mounts": [
            {
                "Type": "volume",
                "Name": "kaven_volume",
                "Source": "/var/lib/docker/volumes/kaven_volume/_data",
                "Destination": "/kaven/volume",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ]      

通过​

​docker run​

​​命令的​

​--volumes-from​

​选项,可以让容器挂载其他容器的数据卷。

docker run -it --name centos.kaven --volumes-from kaven centos:7      
[root@izoq008ryseuupz shared_volume]# docker run -it --name centos.kaven --volumes-from kaven centos:7
[root@5fc01525a699 /]# ll
total 60
-rw-r--r--   1 root root 12114 Nov 13 01:55 anaconda-post.log
lrwxrwxrwx   1 root root     7 Nov 13 01:53 bin -> usr/bin
drwxr-xr-x   5 root root   360 Nov 27 04:33 dev
drwxr-xr-x   1 root root  4096 Nov 27 04:33 etc
drwxr-xr-x   2 root root  4096 Apr 11  2018 home
drwxr-xr-x   3 root root  4096 Nov 27 04:33 kaven
lrwxrwxrwx   1 root root     7 Nov 13 01:53 lib -> usr/lib
lrwxrwxrwx   1 root root     9 Nov 13 01:53 lib64 -> usr/lib64
drwxr-xr-x   2 root root  4096 Apr 11  2018 media
drwxr-xr-x   2 root root  4096 Apr 11  2018 mnt
drwxr-xr-x   2 root root  4096 Apr 11  2018 opt
dr-xr-xr-x 104 root root     0 Nov 27 04:33 proc
dr-xr-x---   2 root root  4096 Nov 13 01:55 root
drwxr-xr-x  11 root root  4096 Nov 13 01:55 run
lrwxrwxrwx   1 root root     8 Nov 13 01:53 sbin -> usr/sbin
drwxr-xr-x   2 root root  4096 Apr 11  2018 srv
dr-xr-xr-x  13 root root     0 Apr 11  2018 sys
drwxrwxrwt   7 root root  4096 Nov 13 01:55 tmp
drwxr-xr-x  13 root root  4096 Nov 13 01:53 usr
drwxr-xr-x  18 root root  4096 Nov 13 01:54 var
[root@5fc01525a699 /]# cd kaven
[root@5fc01525a699 kaven]# ll
total 4
drwxr-xr-x 2 root root 4096 Nov 27 01:24 volume
[root@5fc01525a699 kaven]# cd volume
[root@5fc01525a699 volume]# ll
total 0
[root@5fc01525a699 volume]# exit
exit      

成功挂载了容器​

​kaven​

​的数据卷。

docker inspect centos.kaven      
"Mounts": [
            {
                "Type": "volume",
                "Name": "kaven_volume",
                "Source": "/var/lib/docker/volumes/kaven_volume/_data",
                "Destination": "/kaven/volume",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ]      

类型也是​

​volume​

​。

挂载多个数据卷

可以通过多个​

​-v​

​选项来给容器挂载多个数据卷。

[root@izoq008ryseuupz ~]# docker run -it --name centos.kaven.blog -v one -v two centos:7
[root@7a2ff8ab22f8 /]# ll
total 64
-rw-r--r--  1 root root 12114 Nov 13 01:55 anaconda-post.log
lrwxrwxrwx  1 root root     7 Nov 13 01:53 bin -> usr/bin
drwxr-xr-x  5 root root   360 Nov 25 11:36 dev
drwxr-xr-x  1 root root  4096 Nov 25 11:36 etc
drwxr-xr-x  2 root root  4096 Apr 11  2018 home
lrwxrwxrwx  1 root root     7 Nov 13 01:53 lib -> usr/lib
lrwxrwxrwx  1 root root     9 Nov 13 01:53 lib64 -> usr/lib64
drwxr-xr-x  2 root root  4096 Apr 11  2018 media
drwxr-xr-x  2 root root  4096 Apr 11  2018 mnt
drwxr-xr-x  2 root root  4096 Nov 25 11:36 one
drwxr-xr-x  2 root root  4096 Apr 11  2018 opt
dr-xr-xr-x 96 root root     0 Nov 25 11:36 proc
dr-xr-x---  2 root root  4096 Nov 13 01:55 root
drwxr-xr-x 11 root root  4096 Nov 13 01:55 run
lrwxrwxrwx  1 root root     8 Nov 13 01:53 sbin -> usr/sbin
drwxr-xr-x  2 root root  4096 Apr 11  2018 srv
dr-xr-xr-x 13 root root     0 Apr 11  2018 sys
drwxrwxrwt  7 root root  4096 Nov 13 01:55 tmp
drwxr-xr-x  2 root root  4096 Nov 25 11:36 two
drwxr-xr-x 13 root root  4096 Nov 13 01:53 usr
drwxr-xr-x 18 root root  4096 Nov 13 01:54 var      

通过查询容器信息,可以知道多个数据卷是否全部挂载成功。

docker inspect centos.kaven.blog      
"Mounts": [
            {
                "Type": "volume",
                "Name": "a64fce3680730956d0f0935ef1b5e3695ca5605ef1c6d621cdc6f5d26636bca2",
                "Source": "/var/lib/docker/volumes/a64fce3680730956d0f0935ef1b5e3695ca5605ef1c6d621cdc6f5d26636bca2/_data",
                "Destination": "one",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "6960782eb9ef3472bbce7489f6371fb72c6c0c4107baaf79042ef33dc91fe0f1",
                "Source": "/var/lib/docker/volumes/6960782eb9ef3472bbce7489f6371fb72c6c0c4107baaf79042ef33dc91fe0f1/_data",
                "Destination": "two",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ]      

类型也都是​

​volume​

​。

很显然都挂载成功了。

Docker - Docker数据持久化

数据卷只读权限

通过​

​:ro​

​可以让容器对数据卷的权限变成只读。

docker run -it --name centos.ro -v volume_ro:/volume_ro_kaven:ro centos:7      

可以看到在容器中不能在只读权限数据卷挂载的目录中创建文件夹(其他任何写操作也不可以)。

[root@izoq008ryseuupz shared_volume]# docker run -it --name centos.ro -v volume_ro:/volume_ro_kaven:ro centos:7
[root@3a9b0efd3732 /]# ll
total 60
-rw-r--r--   1 root root 12114 Nov 13 01:55 anaconda-post.log
lrwxrwxrwx   1 root root     7 Nov 13 01:53 bin -> usr/bin
drwxr-xr-x   5 root root   360 Nov 27 04:41 dev
drwxr-xr-x   1 root root  4096 Nov 27 04:41 etc
drwxr-xr-x   2 root root  4096 Apr 11  2018 home
lrwxrwxrwx   1 root root     7 Nov 13 01:53 lib -> usr/lib
lrwxrwxrwx   1 root root     9 Nov 13 01:53 lib64 -> usr/lib64
drwxr-xr-x   2 root root  4096 Apr 11  2018 media
drwxr-xr-x   2 root root  4096 Apr 11  2018 mnt
drwxr-xr-x   2 root root  4096 Apr 11  2018 opt
dr-xr-xr-x 106 root root     0 Nov 27 04:41 proc
dr-xr-x---   2 root root  4096 Nov 13 01:55 root
drwxr-xr-x  11 root root  4096 Nov 13 01:55 run
lrwxrwxrwx   1 root root     8 Nov 13 01:53 sbin -> usr/sbin
drwxr-xr-x   2 root root  4096 Apr 11  2018 srv
dr-xr-xr-x  13 root root     0 Apr 11  2018 sys
drwxrwxrwt   7 root root  4096 Nov 13 01:55 tmp
drwxr-xr-x  13 root root  4096 Nov 13 01:53 usr
drwxr-xr-x  18 root root  4096 Nov 13 01:54 var
drwxr-xr-x   2 root root  4096 Nov 27 04:41 volume_ro_kaven
[root@3a9b0efd3732 /]# cd volume_ro_kaven
[root@3a9b0efd3732 volume_ro_kaven]# mkdir kaven
mkdir: cannot create directory 'kaven': Read-only file system
[root@3a9b0efd3732 volume_ro_kaven]# exit
exit
[root@izoq008ryseuupz shared_volume]# cd /var/lib/docker/volumes/volume_ro/_data
[root@izoq008ryseuupz _data]# mkdir kaven
[root@izoq008ryseuupz _data]# docker start -i centos.ro
[root@3a9b0efd3732 /]# cd volume_ro_kaven
[root@3a9b0efd3732 volume_ro_kaven]# ll
total 4
drwxr-xr-x 2 root root 4096 Nov 27 04:44 kaven      

通过下面这条命令可以查询到数据卷的挂载情况。

docker inspect centos.ro      
"Mounts": [
            {
                "Type": "volume",
                "Name": "volume_ro",
                "Source": "/var/lib/docker/volumes/volume_ro/_data",
                "Destination": "/volume_ro_kaven",
                "Driver": "local",
                "Mode": "ro",
                "RW": false,
                "Propagation": ""
            }
        ]      

类型也是​

​volume​

​​,宿主机中的目录路径​

​"Source": "/var/lib/docker/volumes/volume_ro/_data"​

​​,容器中的目录路径​

​"Destination": "/volume_ro_kaven"​

​​,并且通过​

​"RW": false​

​​、​

​"Mode": "ro"​

​这些信息,说明数据卷只读权限设置成功了。

这些挂载数据卷的方法,对Bind Mount方式进行Docker数据持久化也适用,这里就不介绍了。

继续阅读