GVKun编程网logo

Docker 容器数据卷 - Volume 详解(docker的数据卷)

8

在本文中,我们将带你了解Docker容器数据卷-Volume详解在这篇文章中,我们将为您详细介绍Docker容器数据卷-Volume详解的方方面面,并解答docker的数据卷常见的疑惑,同时我们还将给

在本文中,我们将带你了解Docker 容器数据卷 - Volume 详解在这篇文章中,我们将为您详细介绍Docker 容器数据卷 - Volume 详解的方方面面,并解答docker的数据卷常见的疑惑,同时我们还将给您一些技巧,以帮助您实现更有效的5.docker容器数据卷、Docker (五):容器数据卷 1、Docker Kubernetes Volume 本地数据卷、Docker Kubernetes Volume 网络数据卷

本文目录一览:

Docker 容器数据卷 - Volume 详解(docker的数据卷)

Docker 容器数据卷 - Volume 详解(docker的数据卷)

Docker 中的数据可以存储在类似于虚拟机磁盘的介质中,在 Docker 中称为数据卷(Data Volume)。数据卷可以用来存储 Docker 应用的数据,也可以用来在 Docker 容器间进行数据共享。数据卷呈现给 Docker 容器的形式就是一个目录,支持多个容器间共享,修改也不会影响镜像。使用 Docker 的数据卷,类似在系统中使用 mount 挂载一个文件系统。操作 Docker 数据卷,需要理解以下几点:
============================================================================
1)一个数据卷是一个特别指定的目录,该目录利用容器的 UFS 文件系统可以为容器提供一些稳定的特性或者数据共享。数据卷可以在多个容器之间共享。
============================================================================
2)创建数据卷,只要在 docker run 命令后面跟上 - v 参数即可创建一个数据卷,当然也可以跟多个 - v 参数来创建多个数据卷,当创建好带有数据卷的容器后,就可以在其他容器中通过 --volumes-froms 参数来挂载该数据卷了,而不管该容器是否运行。也可以在 Dockerfile 中通过 VOLUME 指令来增加一个或者多个数据卷。
============================================================================
3)如果有一些数据想在多个容器间共享,或者想在一些临时性的容器中使用该数据,那么最好的方案就是你创建一个数据卷容器,然后从该临时性的容器中挂载该数据卷容器的数据。这样,即使删除了刚开始的第一个数据卷容器或者中间层的数据卷容器,只要有其他容器使用数据卷,数据卷都不会被删除的。
============================================================================
4)不能使用 docker export、save、cp 等命令来备份数据卷的内容,因为数据卷是存在于镜像之外的。备份方法: 创建一个新容器,挂载数据卷容器,同时挂载一个本地目录,然后把远程数据卷容器的数据卷通过备份命令备份到映射的本地目录里面。如下:
docker run --rm --volumes-from DATA -v $(pwd):/backup busybox tar cvf /backup/backup.tar /data
============================================================================
5)可以把一个本地主机的目录当做数据卷挂载在容器上,同样是在 docker run 后面跟 - v 参数,不过 - v 后面跟的不再是单独的目录了,它是 [host-dir]:[container-dir]:[rw|ro] 这样格式的,其中 host-dir 是一个绝对路径的地址,如果 host-dir 不存在,则 docker 会创建一个新的数据卷,如果 host-dir 存在,但是指向的是一个不存在的目录,则 docker 也会创建该目录,然后使用该目录做数据源。

Docker Volume 数据卷可以实现:
-> 绕过 “拷贝写” 系统,以达到本地磁盘 IO 的性能,(比如运行一个容器,在容器中对数据卷修改内容,会直接改变宿主机上的数据卷中的内容,所以是本地磁盘 IO 的性能,而不是先在容器中写一份,最后还要将容器中的修改的内容拷贝出来进行同步。)
-> 绕过 “拷贝写” 系统,有些文件不需要在 docker commit 打包进镜像文件。
-> 数据卷可以在容器间共享和重用数据
-> 数据卷可以在宿主和容器间共享数据
-> 数据卷数据改变是直接修改的
-> 数据卷是持续性的,直到没有容器使用它们。即便是初始的数据卷容器或中间层的数据卷容器删除了,只要还有其他的容器使用数据卷,那么里面的数据都不会丢失。

Docker 数据持久化:
容器在运行期间产生的数据是不会写在镜像里面的,重新用此镜像启动新的容器就会初始化镜像,会加一个全新的读写入层来保存数据。如果想做到数据持久化,Docker 提供数据卷 (Data volume) 或者数据容器卷来解决问题,另外还可以通过 commit 提交一个新的镜像来保存产生的数据。

一、创建一个数据卷

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
如下为容器添加一个数据卷,并将容器名改为data。这个数据卷在容器里的目录是 /opt/data
[root@localhost ~] # docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io /ubuntu     latest              0ef2e08ed3fa        2 weeks ago         130 MB
 
[root@localhost ~] # docker run --name data -v /opt/data -t -i docker.io/ubuntu /bin/bash
root@2b9aebcf6ce8:/ # cd /opt/data/
root@2b9aebcf6ce8: /opt/data # ls
root@2b9aebcf6ce8: /opt/data # echo "123" > 123
root@2b9aebcf6ce8: /opt/data # echo "123123" > 123123
root@2b9aebcf6ce8: /opt/data # ls
123  123123
 
[root@localhost volumes] # docker ps
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS              PORTS                     NAMES
2b9aebcf6ce8        docker.io /ubuntu     "/bin/bash"            49 seconds ago      Up 48 seconds                                 data
 
在宿主机上,查看对应上面的那个数据卷的目录路径:
[root@localhost ~] # docker inspect data|grep /var/lib/docker/volumes
                 "Source" "/var/lib/docker/volumes/89d6562b9c1fe10dd21707cb697a5d481b3c1b000a69b762f540fa826a16972a/_data" ,
[root@localhost ~] # ls /var/lib/docker/volumes/89d6562b9c1fe10dd21707cb697a5d481b3c1b000a69b762f540fa826a16972a/_data
123  123123
[root@localhost ~] # echo "asdhfjashdfjk" >> /var/lib/docker/volumes/89d6562b9c1fe10dd21707cb697a5d481b3c1b000a69b762f540fa826a16972a/_data/123
[root@localhost ~] #
 
root@2b9aebcf6ce8: /opt/data # ls
123  123123
root@2b9aebcf6ce8: /opt/data # cat 123
123
asdhfjashdfjk

二、挂载宿主机文件或目录到容器数据卷

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
可以直接挂载宿主机文件或目录到容器里,可以理解为目录映射,这样就可以让所有的容器共享宿主机数据,从而只需要改变宿主机的数据源就能够影响到所有的容器数据。
 
注意:
- v 后面的映射关系是 "宿主机文件/目录:容器里对应的文件/目录" ,其中,宿主机上的文件/目录是要提前存在的,容器里对应的文件/目录会自动创建。
 
数据卷权限:
挂载的数据默认为可读写权限。
但也可以根据自己的需求,将容器里挂载共享的数据设置为只读,这样数据修改就只能在宿主机上操作。如下实例:
 
1)挂载宿主机文件到容器上
[root@localhost ~] # cat /etc/web.list
192.168.1.100
192.168.1.101
192.168.1.103
[root@localhost ~] # docker run -t -i --name test -v /etc/web.list:/etc/web.list:ro docker.io/centos /bin/bash
[root@e21a3fefa3ae /] # cat /etc/web.list
192.168.1.100
192.168.1.101
192.168.1.103
[root@e21a3fefa3ae /] # echo "192.168.1.115" >> /etc/web.list
bash /etc/web .list: Read-only  file  system
[root@e21a3fefa3ae /] #
  
在宿主机上修改共享数据
[root@localhost ~] # echo "192.168.1.115" >> /etc/web.list
[root@localhost ~] #
  
[root@e21a3fefa3ae /] # cat /etc/web.list
192.168.1.100
192.168.1.101
192.168.1.103
192.168.1.115
 
2)挂载宿主机目录到容器上
[root@localhost ~] # mkdir /var/huanqiupc
[root@localhost ~] # echo "test" > /var/huanqiupc/test
[root@localhost ~] # echo "test1" > /var/huanqiupc/test1
[root@localhost ~] # docker run -t -i --name hqsb -v /var/huanqiupc:/opt/huantime docker.io/centos /bin/bash
[root@87cf93ce46a9 /] # cd /opt/huantime/
[root@87cf93ce46a9 huantime] # ls
test   test1
[root@87cf93ce46a9 huantime] # cat test
test
[root@87cf93ce46a9 huantime] # cat test1
test1
[root@87cf93ce46a9 huantime] # echo "1231" >>test
[root@87cf93ce46a9 huantime] # echo "44444" >>test1
 
宿主机上查看
[root@localhost ~] # cat /var/huanqiupc/test
test
1231
[root@localhost ~] # cat /var/huanqiupc/test1
test1
44444
 
3)挂载多个目录
[root@localhost ~] # mkdir /opt/data1 /opt/data2
[root@localhost ~] # echo "123456" > /opt/data1/test1
[root@localhost ~] # echo "abcdef" > /opt/data2/test2
[root@localhost ~] # docker run --name data -v /opt/data1:/var/www/data1 -v /opt/data2:/var/www/data2:ro -t -i docker.io/ubuntu /bin/bash
root@cf2d57b9bee1:/ # ls /var/www/data1
test1
root@cf2d57b9bee1:/ # ls /var/www/data2
test2
root@cf2d57b9bee1:/ # cat /var/www/data1/test1
123456
root@cf2d57b9bee1:/ # cat /var/www/data2/test2
abcdef
root@cf2d57b9bee1:/ # echo "date1" >> /var/www/data1/test1
root@cf2d57b9bee1:/ # echo "date2" >> /var/www/data2/test2
bash /var/www/data2/test2 : Read-only  file  system
root@cf2d57b9bee1:/ #

三、创建数据卷容器
启动一个名为 xqsj_Container 容器,此容器包含两个数据卷 /var/volume1 和 /var/volume2(这两个数据卷目录是在容器里的,容器创建的时候会自动生成这两目录)

1
2
3
4
5
6
7
8
9
10
注意一个细节:
下面的创建命令中,没有加-t和-i参数,所以这个容器创建好之后是登陆不了的!
-i:表示以“交互模式”运行容器
-t:表示容器启动后会进入其命令行
[root@linux-node2 ~] # docker run -v /var/volume1 -v /var/volume2 --name xqsj_Container centos /bin/bash
[root@linux-node2 ~] #
 
所以要想创建容器后能正常登陆,就需要添加上面两个参数
[root@localhost ~] # docker run -t -i -v /var/volume1 -v /var/volume2 --name xqsj_Container centos /bin/bash
[root@73a34f3c1cd9 /] #

查看宿主机上与数据卷对应的目录路径:

1
2
3
4
[root@localhost ~] # docker inspect xqsj_Container|grep /var/lib/docker/volumes
                 "Source" "/var/lib/docker/volumes/b8d2e5bcadf2550abd36ff5aa544c721a45464a4406fb50979815de773086627/_data" ,
                 "Source" "/var/lib/docker/volumes/a34fa3a0a7a2f126b0d30a32b1034f20917ca7bd0dda346014d768b5ebb68f6b/_data" ,
由上面命令结果可以查到,两个数据卷 /var/volume1 /var/volume2 下的数据在 /var/lib/docker/volumes/ 下对于的两个目录的_data下面

创建 App_Container 容器,挂载 xqsj_Container 容器中的数据卷
[root@linux-node2 ~]# docker run -t -i --rm --volumes-from xqsj_Container --name App_Container centos /bin/bash
[root@b9891bcdfed0 /]# ls /var/volume1                           // 发现这两个数据卷都存在
[root@b9891bcdfed0 /]# ls /var/volume2
[root@b9891bcdfed0 /]# echo "this is volume1" > /var/volume1/test1
[root@b9891bcdfed0 /]# echo "this is volume2" > /var/volume1/test2

可以再创建一个容器,挂载 App_Container 中从 xqsj_Container 挂载的数据卷。当然也可以直接挂载初始的 xqsj_Container 容器数据卷
[root@linux-node2 ~]# docker run -t -i --rm --volumes-from App_Container --name LastApp_Container centos /bin/bash
[root@b4c27e360614 /]# ls /var/volume1
test1
[root@b4c27e360614 /]# ls /var/volume2
test2
[root@b4c27e360614 /]# cat /var/volume1/test1 
this is volume1
[root@b4c27e360614 /]# cat /var/volume2/test2 
this is volume2

即便是删除了初始的数据卷容器 xqsj_Container,或是删除了其它容器,但只要是有容器在使用该数据卷,那么它里面的数据就不会丢失!(除非是没有容器在使用它们)

四、备份数据卷

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
sudo  docker run -- rm  --volumes-from  test  - v  $( pwd ): /backup  ubuntu:14.04  tar  cvf  /backup/test . tar  /test
tar : Removing leading `/'' from member names
/test/
/test/b
/test/d
/test/c
/test/a
  
以上命令表示:
启动一个新的容器并且从 test 容器中挂载卷,然后挂载当前目录到容器中为backup,并备份 test 卷中所有的数据为 test . tar ,执行完成之后删除容器-- rm ,此时备份就在当前的目录下,名为 test . tar
注意:后面的 /test 是数据卷的目录路径(即数据卷创建时在容器里的路径)
  
ls
宿主机当前目录下产生了 test 卷的备份文件 test . tar
  
---------------------------------------------看看下面的一个实例---------------------------------------------
先创建一个容器wang,包含两个数据卷 /var/volume1 /var/volume2 (这两个目录是在容器里的数据卷路径)
[root@localhost ~] # docker run -t -i -v /var/volume1 -v /var/volume2 --name wang docker.io/centos /bin/bash
[root@83eb43492ae7 /] #
  
根据Docker的数据持久化之数据卷容器可知,上面创建的wang数据卷容器挂载了 /var/volume1 /var/volume2 两个目录
然后在数据卷里写些数据,以供测试。
[root@83eb43492ae7 /] # cd /var/volume1
[root@83eb43492ae7 volume1] # echo "test1" > test1
[root@83eb43492ae7 volume1] # echo "test11" > test11
[root@83eb43492ae7 volume1] # echo "test111" > test111
[root@83eb43492ae7 volume1] # ls
test1  test11  test111
[root@83eb43492ae7 volume1] # cd ../volume2
[root@83eb43492ae7 volume2] # echo "test2" > test2
[root@83eb43492ae7 volume2] # echo "test22" > test22
[root@83eb43492ae7 volume2] # echo "test222" > test222
[root@83eb43492ae7 volume2] # ls
test2  test22  test222
[root@83eb43492ae7 volume2] #
  
然后进行这两个数据卷的备份
[root@localhost ~] # docker ps
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS              PORTS                     NAMES
83eb43492ae7        docker.io /centos     "/bin/bash"            2 minutes ago       Up 2 minutes                                  wang
  
  
现在开始进行数据卷的备份操作:
为了利用数据卷容器备份,使用--volumes-from标记来创建一个加载wang容器卷的容器,并从主机挂载当前目录到容器的 /backup 目录。并备份wang卷中的数据,执行完成之后删除容器-- rm ,此时备份就在当前的目录下了。
  
1)备份wang容器中的 /var/volume1 数据卷数据<strong>(注意下面:命令中的-i和-t这两个参数加不加都可以;-- rm 加上,备份后就会自动删除这个容器,如果不加这个-- rm 参数,那么备份后的容器就会保留,docker  ps  -a就会查看到)< /strong >
[root@localhost ~] # docker run -i -t --rm --volumes-from wang -v $(pwd):/backup docker.io/centos tar cvf /backup/backup1.tar /var/volume1
tar : Removing leading `/'' from member names
/var/volume1/
/var/volume1/test1
/var/volume1/test11
/var/volume1/test111
  
2)备份wang容器中的 /var/volume2 数据卷数据
[root@localhost ~] # docker run -i -t --rm --volumes-from wang -v $(pwd):/backup docker.io/centos tar cvf /backup/backup2.tar /var/volume2
tar : Removing leading `/'' from member names
/var/volume2/
/var/volume2/test2
/var/volume2/test22
/var/volume2/test222
  
3)备份wang容器中的 /var/volume1 /var/volume2 数据卷数据
[root@localhost ~] # docker run -i -t --rm --volumes-from wang -v $(pwd):/backup docker.io/centos tar cvf /backup/backup.tar /var/volume1 /var/volume2
tar : Removing leading `/'' from member names
/var/volume1/
/var/volume1/test1
/var/volume1/test11
/var/volume1/test111
/var/volume2/
/var/volume2/test2
/var/volume2/test22
/var/volume2/test222
[root@localhost ~] # ls
anaconda-ks.cfg  a.py  backup1. tar   backup2. tar   backup. tar   mkimage-yum.sh  pipework  var  wang. tar
  
这样,数据卷容器中的数据就备份完成了. 简言之就是:
先创建一个容器,并挂载要备份的容器数据卷,再挂载数据卷( pwd ): /backup 目录到容器 /bakcup ,在容器中执行备份 /data 目录到 /backup ,也就是备份到宿主机$( pwd ): /backup 目录。

五、恢复或迁移数据卷

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
可以恢复给同一个容器或者另外的容器,新建容器并解压备份文件到新的容器数据卷
sudo  docker run -t -i -d - v  /test  --name test4 ubuntu:14.04   /bin/bash
sudo  docker run -- rm  --volumes-from test4 - v  $( pwd ): /backup  ubuntu:14.04  tar  xvf  /backup/test . tar  -C /
恢复之前的文件到新建卷中,执行完后自动删除容器  test test /b  test /d  test /c  test /a
  
-----------------------------接着上面的实例进行数据卷恢复操作--------------------------
[root@localhost ~] # docker ps
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS              PORTS                     NAMES
531c9d8adf4c        docker.io /centos     "/bin/bash"            2 minutes ago       Up 44 seconds                                 wang
  
1)恢复数据给同一个容器
测了测试效果,先删除数据卷(注意:数据卷目录删除不了,只能删除其中的数据。)
[root@localhost ~] # docker attach wang
[root@531c9d8adf4c ~] # ls /var/volume1
test1  test11  test111
[root@531c9d8adf4c ~] # ls /var/volume2
test2  test22  test222
[root@531c9d8adf4c ~] # rm -rf /var/volume1 /var/volume2
rm : cannot remove  ''/var/volume1'' : Device or resource busy 
rm : cannot remove  ''/var/volume2'' : Device or resource busy
[root@531c9d8adf4c ~] # ls /var/volume2
[root@531c9d8adf4c ~] # ls /var/volume1
  
现在进行数据卷恢复,恢复数据卷中的所有数据:
[root@localhost ~] # ls
anaconda-ks.cfg  a.py  backup1. tar   backup2. tar   backup. tar   mkimage-yum.sh  pipework  var  wang. tar
  
注意-C后面的路径,这个路径表示将数据恢复到容器里的路径。
命令中用 "/" ,即表示将backup. tar 中的数据解压到容器的/路径下。后面跟什么路径,就解压到这个路径下。因此这里用 "/"
[root@localhost ~] # docker run --rm --volumes-from wang -v $(pwd):/backup docker.io/centos tar xvf /backup/backup.tar -C /
var /volume1/
var /volume1/test1
var /volume1/test11
var /volume1/test111
var /volume2/
var /volume2/test2
var /volume2/test22
var /volume2/test222
  
再次到容器里查看,发现数据卷里的数据已经恢复了
[root@531c9d8adf4c ~] # ls /var/volume1
test1  test11  test111
[root@531c9d8adf4c ~] # ls /var/volume2
test2  test22  test222
  
2)恢复数据给另外的容器,新建容器并解压备份文件到新的容器数据卷
即新建一个容器huihui,将上面备份的数据卷数据恢复到这个新容器里。
[root@localhost ~] # docker run -t -i -v /var/volume1 -v /var/volume2 --name huihui docker.io/centos /bin/bash
[root@f6ff380e0b7f var] # ls /var/volume1
[root@f6ff380e0b7f var] # ls /var/volume2
  
[root@localhost ~] # ls
anaconda-ks.cfg  a.py  backup1. tar   backup2. tar   backup. tar   mkimage-yum.sh  pipework  var  wang. tar
  
[root@localhost ~] # docker run --rm --volumes-from huihui -v $(pwd):/backup docker.io/centos tar xvf /backup/backup.tar -C /
var /volume1/
var /volume1/test1
var /volume1/test11
var /volume1/test111
var /volume2/
var /volume2/test2
var /volume2/test22
var /volume2/test222
  
[root@localhost ~] # docker ps
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS              PORTS                     NAMES
813afe297b60        docker.io /centos     "/bin/bash"            17 seconds ago      Up 16 seconds                                 huihui
  
  
这里注意一下:
新容器创建时挂载的数据卷路径最好是和之前备份的数据卷路径一致
如下:
1)新建容器挂载的数据卷只是备份数据卷的一部分,那么恢复的时候也只是恢复一部分数据。如下,新容器创建时只挂载 /var/volume1
[root@localhost ~] # docker run -t -i -v /var/volume1 --name huihui docker.io/centos /bin/bash
[root@12dd8d742259 /] # ls /var/volume1/
[root@12dd8d742259 /] # ls /var/volume2
ls : cannot access  /var/volume2 : No such  file  or directory
  
[root@localhost ~] # docker run --rm --volumes-from huihui -v $(pwd):/backup docker.io/centos tar xvf /backup/backup.tar -C /
var /volume1/
var /volume1/test1
var /volume1/test11
var /volume1/test111
var /volume2/
var /volume2/test2
var /volume2/test22
var /volume2/test222
[root@localhost ~] #
  
查看容器,发现只恢复了 /var/volume1 的数据, /var/volume2 数据没有恢复,因为没有容器创建时没有挂载这个。
[root@localhost ~] # docker run -t -i -v /var/volume1 --name huihui docker.io/centos /bin/bash
[root@12dd8d742259 /] # ls /var/volume1/
[root@12dd8d742259 /] # ls /var/volume2
ls : cannot access  /var/volume2 : No such  file  or directory
  
2)新容器创建时只挂载 /var/volume2
[root@localhost ~] # docker run -t -i -v /var/volume2 --name huihui docker.io/centos /bin/bash
[root@da3a3d2c95e0 /] # ls /var/volume2/
[root@da3a3d2c95e0 /] # ls /var/volume1
ls : cannot access  /var/volume1 : No such  file  or directory
  
[root@localhost ~] # docker run --rm --volumes-from huihui -v $(pwd):/backup docker.io/centos tar xvf /backup/backup.tar -C /
var /volume1/
var /volume1/test1
var /volume1/test11
var /volume1/test111
var /volume2/
var /volume2/test2
var /volume2/test22
var /volume2/test222
[root@localhost ~] #
  
[root@da3a3d2c95e0 /] # ls /var/volume1
ls : cannot access  /var/volume1 : No such  file  or directory
[root@da3a3d2c95e0 /] # ls /var/volume2/
test2  test22  test222
  
3)如果新容器创建时挂载的数据卷目录跟之前备份的路径不一致
[root@localhost ~] # docker run -t -i -v /var/huihui --name huihui docker.io/centos /bin/bash
[root@9bad9b3bde71 /] # ls /var/huihui/
[root@9bad9b3bde71 /] #
  
如果解压时-C后面跟的路径不是容器挂载的容器,那么数据恢复不了,如下
[root@localhost ~] # docker run --rm --volumes-from huihui -v $(pwd):/backup docker.io/centos tar xvf /backup/backup.tar -C /
var /volume1/
var /volume1/test1
var /volume1/test11
var /volume1/test111
var /volume2/
var /volume2/test2
var /volume2/test22
var /volume2/test222
  
发现容器内数据没有恢复
[root@9bad9b3bde71 /] # ls /var/huihui/
[root@9bad9b3bde71 /] #
  
但是如果解压时-C后面跟的是容器挂载的路径,数据就能正常恢复
[root@localhost ~] # docker run --rm --volumes-from huihui -v $(pwd):/backup docker.io/centos tar xvf /backup/backup.tar -C /var/huihui
var /volume1/
var /volume1/test1
var /volume1/test11
var /volume1/test111
var /volume2/
var /volume2/test2
var /volume2/test22
var /volume2/test222
[root@localhost ~] #
  
发现容器内数据已经恢复了
[root@9bad9b3bde71 /] # ls /var/huihui/
var
[root@9bad9b3bde71 /] # ls /var/huihui/var/
volume1  volume2
[root@9bad9b3bde71 /] # ls /var/huihui/var/volume1
test1  test11  test111
[root@9bad9b3bde71 /] # ls /var/huihui/var/volume2
test2  test22  test222

六、删除数据卷

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Volume 只有在下列情况下才能被删除:
1)docker  rm  - v 删除容器时添加了- v 选项
2)docker run -- rm 运行容器时添加了-- rm 选项
 
否则,会在 /var/lib/docker/volumes 目录中遗留很多不明目录。
可以使用下面方式找出,然后删除_data目录下的数据文件
[root@localhost volumes] # docker inspect huihui|grep /var/lib/docker/volumes
                 "Source" "/var/lib/docker/volumes/97aa95420e66de20abbe618fad8d0c1da31c54ce97e32a3892fa921c7942d42b/_data" ,
 
可以使用 docker  rm  - v  命令在删除容器时删除该容器的卷。示例如下:
[root@localhost volumes] # docker run -d -P --name huihui -v /www docker.io/centos
69199905a74cb360935e32f4e99f7f11319f6aa36033a920aa0bae25874f5c69
 
[root@localhost volumes] # docker volume ls
DRIVER              VOLUME NAME
local                5341c03f3b94f13f4c86d88ccb0f3b63487adf30dea7ae6b2d06e947235e7330
local                97aa95420e66de20abbe618fad8d0c1da31c54ce97e32a3892fa921c7942d42b
local                data_volume
 
[root@localhost volumes] # docker rm -vf huihui
huihui
[root@localhost volumes] # docker volume ls
DRIVER              VOLUME NAME
local                5341c03f3b94f13f4c86d88ccb0f3b63487adf30dea7ae6b2d06e947235e7330
local                data_volume

=====================  Docker 新版本出现 docker volume 命令:创建数据卷 ======================

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Docker 新版本中引入了 docker volume 命令来管理 Docker volume。
 
使用默认的  ''local''  driver 创建一个volume数据卷
[root@localhost ~] # docker volume create --name kevin
kevin
 
[root@localhost ~] # docker volume ls
DRIVER              VOLUME NAME
local                kevin
 
[root@localhost ~] # ll /var/lib/docker/volumes
total 24
drwxr-xr-x 3 root root    19 Oct 28 00:32 kevin
-rw------- 1 root root 32768 Oct 28 00:32 metadata.db
 
使用这个名为kevin的数据卷
[root@localhost ~] # docker run -d -P --name test1 -v kevin:/volume docker.io/centos
375ef74722404f5c52fde9f2ea7ea322c57e07fbac0b0e69825f077328fdb363
 
[root@localhost ~] # docker inspect test1
.........
  "Mounts" : [
             {
                 "Type" "volume" ,
                 "Name" "kevin" ,
                 "Source" "/var/lib/docker/volumes/kevin/_data" ,
                 "Destination" "/volume" ,
                 "Driver" "local" ,
                 "Mode" "z" ,
                 "RW" true ,
                 "Propagation" ""
             }
 
 
即将kevin数据卷对应在本机上的目录 /var/lib/docker/volumes/kevin/_data 挂载给容器内的  /volume  目录。

5.docker容器数据卷

5.docker容器数据卷

docker基础

1. docker前言知识(重要: 知道为什么学,比学什么更重要): https://www.cnblogs.com/ITPower/p/12945685.html

2. docker架构,原理,安装及简单应用: https://www.cnblogs.com/ITPower/p/12945711.html

3. docker容器的命令: https://www.cnblogs.com/ITPower/p/12664292.html

4. 镜像的原理: https://www.cnblogs.com/ITPower/p/12975385.html

 

目录:

1. docker数据卷的添加方式,有两种: 命令添加,dockerfile添加

2. 数据加载卷共享: --volumes-from

 

一. 数据卷的添加方式

有两种:

1.1 . 直接命令添加

1. 命令

docker run -it -v /宿主机绝对路径目录:/容器绝对路径目录 镜像名

 

 -v命令除了可以挂在目录,还有mkdir的作用. 也就是说,如果挂在的目录不存在,那么他会自动创建目录

 

2. 查看数据卷是否挂在成功

docker inspect 容器id

docker inspect d804cc6b6e31,看到挂在信息Mounts. 我们看到RW,表示可以读写

 

 

3. 容器和宿主机之间共享数据

在容器中创建数据,宿主机可以共享. 在宿主机创建数据,容器可以共享到.

4. 容器停止退出后,主机修改的数据依然共享

5. 设置带有权限的容器

有时,我们只允许容器读数据,不允许容器写数据. 这个怎么操作呢?

docker run -it -v /宿主机绝对路径目录:/容器绝对路径目录:ro 镜像id

这里的ro表示的是read only,只读

这是我们使用docker inspect 容器id查看挂在详情

 

1.2  Dockerfile添加

简单了解一下,dockerfile是什么?

我们用类比的思想. 
java 中 hello.java,----> hello.class 源码文件
docker中 image----->dockerfile  

也就是说,hello.class是hello.java的源码文件. 而dockerfile就是image的源码文件

下面我们来看看如何用dockerfile写容器目录的挂载

1. 学习别人是怎么写dockerfile的

我们可以看看别人的dockerfile是怎么写的

在hub.docker.com中搜索tomcat. 我们来看看tomcat的dockerfile

FROM openjdk:11-jdk

ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH
RUN mkdir -p "$CATALINA_HOME"
workdir $CATALINA_HOME

# let Tomcat Native live somewhere isolated
ENV TOMCAT_NATIVE_LIBDIR $CATALINA_HOME/native-jni-lib
ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOMCAT_NATIVE_LIBDIR

# see https://www.apache.org/dist/tomcat/tomcat-$TOMCAT_MAJOR/KEYS
# see also update.sh" (https:github.com/docker-library/tomcat/blob/master/update.sh)
ENV GPG_KEYS 05AB33110949707C93A279E3D3EFE6B686867BA6 07E48665A34DCAFAE522E5E6266191C37C037D42 47309207D818FFD8DCD3F83F1931D684307A10A5 541FBE7D8F78B25E055DDEE13C370389288584E7 61B832AC2F1C5A90F0F9B00A1C506407564C17A3 713DA88BE50911535FE716F5208B0AB1D63011C7 79F7026C690BAA50B92CD8B66A3AD3F4F22C4FED 9BA44C2621385CB966EBA586F72C284D731FABEE A27677289986DB50844682F8ACB77FC2E86E29AC A9C5DF4D22E99998D9875A5110C01C5A2F6059E7 DCFD35E0BF8CA7344752DE8B6FB21E8933C60243 F3A04C595DB5B6A5F1ECA43E3B7BBB100D811BBE F7DA48BB64BCB84ECBA7EE6935CD23C10D498E23

ENV TOMCAT_MAJOR 8
ENV TOMCAT_VERSION 8.5.55
ENV TOMCAT_SHA512 996b653b4f81b40ae3620d6424593d23687e5ceb5cbd7357fc8d0e4b92f76903fe7fb20bf7316505e4e86269153fbfe62394bf45e59b4fb1cbc1bc95fad9eb7a

RUN set -eux; \
    \
    savedAptMark=$(apt-mark showmanual); \
    apt-get update; \
    apt-get install -y --no-install-recommends \
        gnupg dirmngr \
        wget ca-certificates \
    ; \
    \
    ddist() { \
        local f=$1; shift; \
        local distFile=; shift; \
        local mvnFile=${1:-}; \
        local success=; \
        local distUrl=; \
        for distUrl in \
# https:issues.apache.org/jira/browse/INFRA-8753?focusedCommentId=14735394#comment-14735394
            https://www.apache.org/dyn/closer.cgi?action=download&filename=$distFile \
# if the version is outdated (or we're grabbing the .asc file),we might have to pull from the dist/archive :/
            https://www-us.apache.org/dist/$distFile \
            https://www.apache.org/dist/$distFilehttps://archive.apache.org/dist/$distFileif all else fails,lets try Maven (https://www.mail-archive.com/users@tomcat.apache.org/msg134940.html; https://mvnrepository.com/artifact/org.apache.tomcat/tomcat; https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/)
            ${mvnFile:+https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/$mvnFile} \
        ; do \
            if wget -O $f" $distUrl" && [ -s  ]; then \
                success=1; \
                break; \
            fi; \
        done; \
        [ -n $success ]; \
    }; \
    \
    ddist tomcat.tar.gz' tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz$TOMCAT_VERSION/tomcat-$TOMCAT_VERSION.tar.gz; \
    echo $TOMCAT_SHA512 *tomcat.tar.gz" | sha512sum --strict --check -; \
    ddist tomcat.tar.gz.asctomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz.asc$TOMCAT_VERSION/tomcat-$TOMCAT_VERSION.tar.gz.asc; \
    export GNUPGHOME=$(mktemp -d); \
    for key in $GPG_KEYS;  \
        gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys $key; \
    done; \
    gpg --batch --verify tomcat.tar.gz.asc tomcat.tar.gz; \
    tar -xf tomcat.tar.gz --strip-components=; \
    rm bin/*.bat; \
    rm tomcat.tar.gz*; \
    command -v gpgconf && gpgconf --kill all || :; \
    rm -rf "$GNUPGHOME"; \
    \
# https://tomcat.apache.org/tomcat-9.0-doc/security-howto.html#Default_web_applications
    mv webapps webapps.dist; \
    mkdir webapps; \
# we don't delete them completely because they're frankly a pain to get back for users who do want them,and they're generally tiny (~7MB)
    \
    nativeBuildDir="$(mktemp -d)"; \
    tar -xf bin/tomcat-native.tar.gz -C "$nativeBuildDir" --strip-components=1; \
    apt-get install -y --no-install-recommends \
        dpkg-dev \
        gcc \
        libapr1-dev \
        libssl-dev \
        make \
    ; \
    ( \
        export CATALINA_HOME="$PWD"; \
        cd "$nativeBuildDir/native"; \
        gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
        aprConfig="$(command -v apr-1-config)"; \
        ./configure \
            --build="$gnuArch" \
            --libdir="$TOMCAT_NATIVE_LIBDIR" \
            --prefix="$CATALINA_HOME" \
            --with-apr="$aprConfig" \
            --with-java-home="$JAVA_HOME" \
            --with-ssl=yes; \
        make -j "$(nproc)"; \
        make install; \
    ); \
    rm -rf "$nativeBuildDir"; \
    rm bin/tomcat-native.tar.gz; \
    \
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
    apt-mark auto '.*' > /dev/null; \
    [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \
    find "$TOMCAT_NATIVE_LIBDIR" -type f -executable -exec ldd '{}' ';' \
        | awk '/=>/ { print $(NF-1) }' \
        | sort -u \
        | xargs -r dpkg-query --search \
        | cut -d: -f1 \
        | sort -u \
        | xargs -r apt-mark manual \
    ; \
    apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
    rm -rf /var/lib/apt/lists/*; \
    \
# sh removes env vars it doesn't support (ones with periods)
# https://github.com/docker-library/tomcat/issues/77
    find ./bin/ -name '*.sh' -exec sed -ri 's|^#!/bin/sh$|#!/usr/bin/env bash|' '{}' +; \
    \
# fix permissions (especially for running as non-root)
# https://github.com/docker-library/tomcat/issues/35
    chmod -R +rX .; \
    chmod 777 logs temp work

# verify Tomcat Native is working properly
RUN set -e \
    && nativeLines="$(catalina.sh configtest 2>&1)" \
    && nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')" \
    && nativeLines="$(echo "$nativeLines" | sort -u)" \
    && if ! echo "$nativeLines" | grep -E 'INFO: Loaded( APR based)? Apache Tomcat Native library' >&2; then \
        echo >&2 "$nativeLines"; \
        exit 1; \
    fi

EXPOSE 8080
CMD ["catalina.sh","run"]

这是tomcat的dockerfile,我们分解来看看

FROM openjdk:11-jdk
FROM相当于java中的extends. 继承自父类. 也就是说,tomcat运行,依赖于openjdk.
这就是为什么tomcat很大的原因,因为他依赖其他镜像而存在.
ENV CATALINA_HOME /usr/local/bin:$PATH

这里是设置环境变量
EXPOSE 8080


设置tomcat对外暴露的端口号是8080
CMD [catalina.sh",run]

执行命令,启动并运行tomcat

 

2. 编写带有挂载目录的dockerfile

那么下面我们来写一个挂载目录的dockerfile

可在dockerfile中使用VOLUME命令来给镜像添加一个或多个数据卷

VLOUME["容器目录1","容器目录2","容器目录3"]

备注: 

处于可移植和分享的考虑,用-v /宿主机目录:/容器目录 这种方法不能够直接在Dockerfile中使用

由于宿主机目录是依赖于特定主机的,并不能够保证在所有的宿主机上都存在这样的目录. 

所以,这里只设置容器挂载目录,与宿主机的对应目录,自动生成,可以试用docker inspect查看详情

 

我们可以参考着上面的tomcat来写

FROM centos
VOLUME [/dataVolumeContainer1/dataVolumeContainer2/dataVolumeContainer3]
CMD echo finish.......success!!
CMD /bin/bash

这是一个很简单的dockerfile,依赖的父类镜像是centos,启动的容器,只做了一个目录挂载. 

这个dockerfile写好了以后,是什么意思呢? 大致可以理解为一下的含义

docker run -it -v /HOST:/dataVolumeContainer1 -v /HOST:/dataVolumeContainer2 -v /HOST:/dataVolumeContainer3 镜像ID /bin/bash

只是,上面没有定义宿主机挂载的目录. 

3. build生成镜像

docker build -f dockerfile目录  -t 新的镜像名字 .
docker build -f /docker/dockerfile/dockerfile -t lxl/centos .

 

 就像洋葱一样,一层套一层.

 4. 运行容器

查看镜像

docker images

 

 我们看到了刚刚生成的镜像. 这个镜像就是带有挂载目录的镜像. 我们可以通过运行容器查看挂载目录

docker run -it 5a8ecf996d8d

 

 进来直接就可以看到挂载目录. 那么在容器和宿主机创建的目录,都可以被共享

 

比如: 我们在/dataVolumeContainer1中创建一个文件

 

5. 查看目录挂载

 使用docker inspect查看宿主机中挂载目录

docker inspect 0dcff7fc2508

 

 我们可以看到,在宿主机上生成了一个默认的挂载目录. 

进入第一个目录,看看能否看到刚刚创建的container.txt文件

 确实是可以共享

 

备注: Docker挂载主机目录Docker访问出现cannot open directory .: Permission denied

解决办法: 在挂载目录后多加一个 --privileged=true 参数即可

 二. 容器数据卷

2.1. 什么是容器数据卷?

命名的容器挂载数据卷,其他的容器通过挂载这个父容器实现数据共享,挂载数据卷的容器,称之为数据卷容器.

2.2. 构建容器数据卷

以上一步新建的镜像lxl/centos为模板并运行容器dc01/dc02/dc03

他们已经具有容器卷/dataVolumeContainer1,/dataVolumeContainer2,/dataVolumeContainer3

 

容器间传递共享数据--volumes-from

下面演示一下. 具体操作

1. 先启动一个父容器dc01,在/dataVolumeContainer2中新增内容

docker run -it --name dc01 lxl/centos

上面我创建了一个带有挂载卷的镜像lxl/centos. 这里启动的就是这个镜像

--name 指定容器的名字是dc01,如果不指定会默认生成一个

接下来我们来查看是否有挂载卷目录

 

 

 

 

 

 果然,生来自带三个目录

 

现在,我们向目录1中写入文件

 

 

 

 

 

2. dc2/dc3继承自dc1,  --volumes-from

  • 退出dc01容器,但不要关闭,使用命令
ctrl + p + q

 

  • 先创建dc02,继承自dc01容器
 docker run -it --name dc02 --volume-from dc01 lxl/centos

--volume-from : 继承自父类容器dc01的加载卷
使用的镜像依然是lxl/centos
--name : 给容器命名为dc02

 

  • 查看dc02中是否能够看到刚刚在dc01中创建的文件dc01.txt

 

 

 没问题,我们确实能够看到dc01创建的文件

 

  • 接下来,我们在dc02创建一个文件

 

 

 

  • 退出dc02 容器
ctrl + p + q

 

  • 进入dc01容器,看看是否能够看到刚刚dc02创建的dc02.txt

 

 

我们确实看到了,这说明,dc01 和 dc02 的数据卷是共享

 

  • 在创建一个dc03容器,继承自dc01,方法和dc02的创建类
[root@localhost ~]# docker run -it --name dc03 --volumes-from dc01 lxl/centos
[root@8545291ec601 /]# 
]# ls  
bin  dataVolumeContainer1  dataVolumeContainer2  dataVolumeContainer3  dev  etc  home  lib  lib64  lost+found  media  mnt  opt    proc  root  run  sbin  srv  sys  tmp  usr  var
[root@8545291ec601 /]# cd dataVolumeContainer1 
[root@8545291ec601 dataVolumeContainer1]# ls
dc01.txt  dc02.txt
[root@8545291ec601 dataVolumeContainer1]# touch dc03.txt
[root@8545291ec601 dataVolumeContainer1]# ls
dc01.txt  dc02.txt  dc03.txt

如上面命令,我们在dc03容器中创建了dc03.txt,查看dc01和dc02也是都可以看到的.

 

3. 问题1: 删除掉dc01,dc02和dc03的加载卷是否会被删除呢? 

查询当前启动的容器,dc01,dc02,dc03 都是启动中的状态
[root@localhost ~
]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8545291ec601 lxl/centos /bin/sh -c /bin/bash" 4 minutes ago Up 4 minutes dc03 d1cdf1ba3148 lxl/centos 12 minutes ago Up 12 minutes dc02 52a9525a9598 lxl/centos 20 minutes ago Up 20 minutes dc01 0dcff7fc2508 5a8ecf996d8d 22 hours ago Up 22 hours objective_mcclintock

停止dc01容器,我们知道dc02和dc03都是继承自dc01,那么dc01停止以后,dc02和dc03的数据卷还会共享么?
[root@localhost
~]# docker stop 52a9525a9598 52a9525a9598 minutes dc02 0dcff7fc2508 5a8ecf996d8d hours objective_mcclintock ~]# [root@localhost ~]#


进入dc02容器,我们发现,dc02容器依然拥有数据卷,下面的文件也都存在,dc03也是如此 [root@localhost ~
]# docker attach dc02 [root@d1cdf1ba3148 dataVolumeContainer1]# ls
dc01.txt dc02.txt dc03.txt


 

 dc03也是如此

  [root@localhost ~]# docker attach dc03

  [root@8545291ec601 dataVolumeContainer1]# ls

  dc01.txt  dc02.txt  dc03.txt

 

 

4. 问题2: 删掉dc01以后,dc03创建的文件,是否可以和dc02共享呢?

现在是在dc03容器里面,数据卷里有3个文件,然后创建一个新的文件dc03-2.txt
[root@8545291ec601 dataVolumeContainer1]#
ls dc01.txt dc02.txt dc03.txt [root@8545291ec601 dataVolumeContainer1]# touch dc03-2.txt [root@8545291ec601 dataVolumeContainer1]# ls dc01.txt dc02.txt dc03-.txt dc03.txt [root@8545291ec601 dataVolumeContainer1]# [root@localhost ~]# [root@localhost ]#


文件. 我们发现,确实看到了 ]#
docker attach dc02 [root@d1cdf1ba3148 dataVolumeContainer1]# ls dc01.txt dc02.txt dc03-2.txt dc03.txt

 

总结: 以上两个问题说明:容器之间信息的传递,数据卷的生命周期一直持续到所有的容器生命周期全部结束

仔细想想原因是什么? 

因为dc01,dc03他们都是挂载在宿主机上. 他们每一次数据的改动都会被同步到宿主机. 他们最终的文件内容是和宿主机保持一致的.

 

----------

最后来回顾一下,dockerfile容器挂载的几个步骤

1. 编写dockerfile文件

2. build生成镜像

3. 启动容器

4. 查看挂载卷. 

5. 容器间共享数据卷 --volumes-from

 

Docker (五):容器数据卷 1

Docker (五):容器数据卷 1

一、是什么

先来看看 Docker 的理念:

  • 将运用与运行的环境打包形成容器运行,运行可以伴随着容器,但是我们对数据的要求希望是持久化的
  • 容器之间希望有可能共享数据

Docker 容器产生的数据,如果不通过 docker commit 生成新的镜像,使得数据做为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了。

为了能保存数据在 docker 中我们使用卷。

有点类似 redis 的 RDB 和 AOF 文件。

卷就是目录或文件,存在于一个或多个容器中,由 docker 挂载到容器, 但不属于联合文件系统,因此能够绕过 Union File System 提供一些用于持续存储或共享数据的特性:

卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此 Docker 不会在容器删除时删除其挂载的数据卷。

特点:

  • 数据卷可在容器之间共享或重用数据
  • 卷中的更改可以直接生效
  • 数据卷中的更改不会包含在镜像的更新中
  • 数据卷的生命周期一直持续到没有容器使用它为止

二、能做什么

  • 容器的持久化
  • 容器间继承 + 共享数据

三、数据卷(用命令增加)

主要命令:

  • docker run -it -v / 宿主机目录:/ 容器目录 容器 id / 容器名称 (不带权限,可读可写 v:Volume 卷)
  • docker run -it -v / 宿主机目录:/ 容器目录:ro 容器 id / 容器名称 (带权限,可读不可写 ro:read only)

1、打开多个终端:container 终端、宿主机终端 1、宿主机终端 2

生成数据卷之前,先分别查看宿主机和容器根目录下的文件
容器终端

[root@localhost ~]# docker run -it centos /bin/bash
[root@7a3b16c431e0 /]# ls
anaconda-post.log  bin  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@7a3b16c431e0 /]# exit 
exit

宿主机终端 1

[root@localhost ~]# cd ../
[root@localhost /]# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt opt  proc  root  run  sbin  srv  sys  tmp  usr  var

容器终端
执行命令
docker run -it -v / 宿主机目录:/ 容器目录 容器 id / 容器名称

[root@localhost ~]# docker run -it -v /myDataVolume:/dataVolumeContainer centos
[root@edd30dad389b /]# ls
anaconda-post.log  bin  dataVolumeContainer  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

宿主机终端 1

[root@localhost /]# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  myDataVolume  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

可以发现宿主机和容器内都增加了一个文件夹

宿主机终端 2

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
edd30dad389b        centos              "/bin/bash"         3 minutes ago       Up 3 minutes                            gallant_borg
[root@localhost ~]# docker inspect edd30dad389b
## 仅展示本文需要的信息
"Mounts": [
            {
                "Type": "bind",
                "Source": "/myDataVolume",
                "Destination": "/dataVolumeContainer",
                "Mode": "",
                "RW": true, ## 可以进行读写操作
                "Propagation": "rprivate"
            }
        ]
"Binds": [
                "/myDataVolume:/dataVolumeContainer" ## 表示容器内部已和宿主机对应的文件夹绑定
            ]

2、实现继承 + 共享数据

宿主机终端 1

[root@localhost /]# cd myDataVolume/
[root@localhost myDataVolume]# ls
[root@localhost myDataVolume]# touch host.txt
[root@localhost myDataVolume]# ll
总用量 0
-rw-r--r--. 1 root root 0 1011 10:21 host.txt

容器终端

[root@edd30dad389b /]# cd dataVolumeContainer/
[root@edd30dad389b dataVolumeContainer]# ll
total 0
-rw-r--r--. 1 root root 0 Oct 11 02:21 host.txt

可以看到宿主机在绑定的文件夹里创建文件的同时,容器内部对应的文件夹里也同时创建了文件

容器终端

[root@edd30dad389b dataVolumeContainer]# vi host.txt 
## 写入container update 666 并保存退出
[root@edd30dad389b dataVolumeContainer]# touch container.txt
[root@edd30dad389b dataVolumeContainer]# ll
total 4
-rw-r--r--. 1 root root  0 Oct 11 02:27 container.txt
-rw-r--r--. 1 root root 21 Oct 11 02:24 host.txt

宿主机终端 1

[root@localhost myDataVolume]# ll
总用量 4
-rw-r--r--. 1 root root  0 10 11 10:27 container.txt
-rw-r--r--. 1 root root 21 10 11 10:24 host.txt
[root@localhost myDataVolume]# cat host.txt 
container update 666

可以发现无论是哪个端进行增删改文件及内容,均能相互共享

3、容器停止后,宿主机修改后能否同步数据

容器终端

[root@edd30dad389b dataVolumeContainer]# exit
exit
[root@localhost ~]#

宿主机终端 2

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

宿主机终端 1

[root@localhost myDataVolume]# touch host01.txt
[root@localhost myDataVolume]# vim host.txt 
## 写入host update 666 并保存退出

[root@localhost myDataVolume]# ll 
总用量 4
-rw-r--r--. 1 root root  0 10 11 10:27 container.txt
-rw-r--r--. 1 root root  0 10 11 10:44 host01.txt
-rw-r--r--. 1 root root 37 10 11 10:44 host.txt

容器终端
重启上次的容器 id

[root@localhost ~]# docker start edd30dad389b
edd30dad389b

宿主机终端 2

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
edd30dad389b        centos              "/bin/bash"         About an hour ago   Up 3 seconds                            gallant_borg

容器终端

[root@localhost ~]# docker attach edd30dad389b
[root@edd30dad389b /]# cd dataVolumeContainer/
[root@edd30dad389b dataVolumeContainer]# ll
total 4
-rw-r--r--. 1 root root  0 Oct 11 02:27 container.txt
-rw-r--r--. 1 root root 37 Oct 11 02:44 host.txt
-rw-r--r--. 1 root root  0 Oct 11 02:44 host01.txt
[root@edd30dad389b dataVolumeContainer]# cat host.txt 
container update 666
host update 666

没问题,可以同步

4、命令带权限

宿主机终端 1

[root@localhost myDataVolume]# cd ../
[root@localhost /]# rm -rf myDataVolume/
[root@localhost /]# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

容器终端

[root@edd30dad389b dataVolumeContainer]# ll
total 0
[root@edd30dad389b dataVolumeContainer]# cd ../
[root@edd30dad389b /]# ls
anaconda-post.log  bin  dataVolumeContainer  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@edd30dad389b /]# exit 
exit

[root@localhost ~]# docker run -it -v /myDataVolume:/dataVolumeContainer:ro centos
[root@2388132eddd0 /]# ls
anaconda-post.log  bin  dataVolumeContainer  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@2388132eddd0 /]# cd dataVolumeContainer/
[root@2388132eddd0 dataVolumeContainer]# ll
total 0

宿主机终端 1

[root@localhost /]# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  myDataVolume  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@localhost /]# cd myDataVolume/
[root@localhost myDataVolume]# ll
总用量 0
[root@localhost myDataVolume]# touch host.txt
[root@localhost myDataVolume]# vim host.txt 
[root@localhost myDataVolume]# cat host.txt 
host update 

容器终端

[root@2388132eddd0 dataVolumeContainer]# ll
total 0
-rw-r--r--. 1 root root 0 Oct 11 03:14 host.txt
[root@2388132eddd0 dataVolumeContainer]# cat host.txt 
host update 

重点来了
容器终端

[root@2388132eddd0 dataVolumeContainer]# touch container.txt
touch: cannot touch ''container.txt'': Read-only file system
[root@2388132eddd0 dataVolumeContainer]# vi host.txt 
"host.txt"
"host.txt" E212: Can''t open file for writing ## vi 操作则会提示

说明权限命令没问题,只允许宿主机单向传给容器,容器不能反向传给宿主机

宿主机终端 2

"Binds": [
                "/myDataVolume:/dataVolumeContainer:ro" ## 加上了:ro
            ]

"Mounts": [
            {
                "Type": "bind",
                "Source": "/myDataVolume",
                "Destination": "/dataVolumeContainer",
                "Mode": "ro",
                "RW": false, ## 此时RW为false
                "Propagation": "rprivate"
            }
        ]

Docker Kubernetes Volume 本地数据卷

Docker Kubernetes Volume 本地数据卷

Docker Kubernetes Volume 本地数据卷

emptyDir

  • 当 Pod 分配到 Node 时,首先创建一个空卷,并挂载到 Pod 中的容器。
  • Pod 中的容器可以读取和写入卷中的文件。
  • 当 Pod 从节点中删除 emptyDir 时,该数据也会被删除。
  • 注:适用于容器之间的数据共享。

hostPath

  • 一个 hostPath 卷挂载 Node 文件系统上的文件或目录到 Pod 中的容器。
  • 注:指定宿主级的数据目录挂载到容器中。

环境:

  • 系统:Centos 7.4 x64
  • Docker 版本:18.09.0
  • Kubernetes 版本:v1.8
  • 管理节点:192.168.1.79
  • 工作节点:192.168.1.78
  • 工作节点:192.168.1.77

创建 emptydir 实例

1、管理节点:创建 yaml 文件

vim emptydir.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: nginx:1.12
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}
# api版本
apiVersion: v1
# 指定创建资源对象
kind: Pod
# 源数据、可以写name,命名空间,对象标签
metadata:
# 服务名称
  name: test-pd
# 容器资源信息
spec:
# 容器管理
  containers:
# 镜像名称
  - image: nginx:1.12
# 容器名称
    name: test-container
# 容器数据卷管理
    volumeMounts:
# 容器内挂载目录
    - mountPath: /cache
# 容器挂载数据名称
      name: cache-volume
# 宿主数据卷管理
  volumes:
# 创建数据卷名称
  - name: cache-volume
# emptydir标准语法
    emptyDir: {}
文件注解

2、管理节点:创建 Pod

kubectl create -f emptydir.yaml

3、测试

命令:kubectl exec test-pd -it bash

root@test-pd:/# cd /cache/
root@test-pd:/cache# ls
root@test-pd:/cache#
测试挂载路径
命令:kubectl describe pods test-pd

    Mounts:
      /cache from cache-volume (rw)
Conditions:
  Type           Status
  Initialized    True 
  Ready          True 
  PodScheduled   True 
Volumes:
  cache-volume:
    Type:        EmptyDir (a temporary directory that shares a pod''s lifetime)
    Medium:      
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     <none>
查看容器挂载信息

创建 hostPath 实例

1、管理节点:创建 yaml 文件

apiVersion: v1
kind: Pod
metadata:
  name: test-pd2
spec:
  containers:
  - image: nginx:1.12
    name: test-container
    volumeMounts:
    - mountPath: /data
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      path: /etc/default
      type: Directory
# api版本
apiVersion: v1
# 指定创建资源对象
kind: Pod
# 源数据、可以写name,命名空间,对象标签
metadata:
# 服务名称
  name: test-pd2
# 容器资源信息
spec:
# 容器管理
  containers:
# 镜像名称
  - image: nginx:1.12
    name: test-container
# 容器数据卷管理
    volumeMounts:
# 容器挂载目录
    - mountPath: /data
# 容器挂载数据名称
      name: test-volume
# 宿主数据卷管理
  volumes:
# 创建数据卷名称
  - name: test-volume
# 数据卷地址
    hostPath:
# 挂载到容器的宿主目录
      path: /etc/default
# 类型为目录文件
      type: Directory
文件注解

2、管理节点:创建 Pod

kubectl create -f hostpath.yaml

3、测试

命令:kubectl exec test-pd2 -it bash

root@test-pd2:/# cd /data
root@test-pd2:/data# ls
grub  nss  useradd  yyy

 

Docker Kubernetes Volume 网络数据卷

Docker Kubernetes Volume 网络数据卷

Docker Kubernetes Volume 网络数据卷

由于支持网络数据卷众多 今天只拿 nfs 作为案例。

支持网络数据卷

  • nfs
  • iscsi
  • glusterfs
  • awsElasticBlockStore
  • cephfs
  • azureFileVolume
  • azureDiskVolume
  • vsphereVolume
  • .....

环境:

  • 系统:Centos 7.4 x64
  • Docker 版本:18.09.0
  • Kubernetes 版本:v1.8
  • 管理节点:192.168.1.79
  • 工作节点:192.168.1.78
  • 工作节点:192.168.1.77

一、搭建 NFS 服务与客户端

1、管理节点:安装 nfs 服务端、配置 nfs 主配置文件、添加权限、启动

yum install nfs-utils -y
vim /etc/exports
# 添加目录给相应网段访问并添加读写权限 /data 192.168.1.0/24(insecure,rw,async,no_root_squash)
# 创建共享目录,添加权限
mkdir -p /data
chmod 777 /data
# 开启rpc服务
systemctl start rpcbind
# 启动服务并设置开机自启 systemctl start nfs

2、工作节点:安装 nfs 客户端、启动服务

yum install nfs-utils -y
# 开启rpc服务
systemctl start rpcbind
# 启动服务并设置开机自启
systemctl start nfs

二、共享 NFS 网络数据卷

1、管理节点:创建 yaml 文件

vim nginx-nfs.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment-nfs
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.10
        volumeMounts:
        - name: wwwroot
          mountPath: /var/www/html
        ports:
        - containerPort: 80
      volumes:
      - name: 
        nfs:
          server: 192.168.1.79
          path: /data
# 指定api版本
apiVersion: extensions/v1beta1
# 指定需要创建的资源对象
kind: Deployment
# 源数据、可以写name,命名空间,对象标签
metadata:
# 指定对象名称
  name: nginx-deployment2-nfs
# 描述资源相关信息
spec:
# 指定pod 副本数,默认1
  replicas: 3
# 描述资源具体信息
  template:
# 匹配标签字段
    metadata:
# 指定pod标签value:key
      labels:
# 标签名
        app: nginx
# 管理容器
    spec:
# 指定容器信息
      containers:
# 指定容器名称
      - name: nginx
# 指定镜像名称
        image: nginx:1.10
# 网络数据卷管理
        volumeMounts:
# 数据卷名称
        - name: wwwroot
# 容器数据卷挂载路径
          mountPath: /var/www/html
# 端口管理
        ports:
# 暴露端口
        - containerPort: 80
# 网络共享数据卷管理
      volumes:
# 数据卷名称两边需要相同
      - name: wwwroot
# 数据卷类型为nfs
        nfs:
# NFS服务器地址
          server: 192.168.1.79
# 服务端共享路径
          path: /data
文件注解

2、管理节点:创建 Deployment

kubectl create -f nginx-nfs.yaml
命令:kubectl get pods -o wide

NAME                                    READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-deployment-nfs-5fbcddddb6-7btt4   1/1       Running   0          55s       172.17.2.11   192.168.1.78
nginx-deployment-nfs-5fbcddddb6-sf6bz   1/1       Running   0          55s       172.17.2.10   192.168.1.78
nginx-deployment-nfs-5fbcddddb6-ws8wk   1/1       Running   0          55s       172.17.1.9    192.168.1.77
查看创建情况
命令:kubectl describe nginx-deployment-nfs-5fbcddddb6-sf6bz

    Mounts:
      /var/www/html from wwwroot (rw)
Conditions:
  Type           Status
  Initialized    True 
  Ready          True 
  PodScheduled   True 
Volumes:
  wwwroot:
    Type:        NFS (an NFS mount that lasts the lifetime of a pod)
    Server:      192.168.1.79
    Path:        /data
    ReadOnly:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     <none>
reated container
查看详细信息

3、测试

# 1、宿主端nfs共享文件内创建文件
命令:touch /data/123

# 2、进入容器内查看文件是否共享
命令:kubectl exec nginx-deployment-nfs-5fbcddddb6-sf6bz -it bash

root@nginx-deployment-nfs-5fbcddddb6-sf6bz:/# ls /var/www/html/
123

 

关于Docker 容器数据卷 - Volume 详解docker的数据卷的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于5.docker容器数据卷、Docker (五):容器数据卷 1、Docker Kubernetes Volume 本地数据卷、Docker Kubernetes Volume 网络数据卷等相关知识的信息别忘了在本站进行查找喔。

本文标签: