前言:
docker数据卷
- 数据卷是目录或文件,不是块设备。
- 容器可以读写volume中的数据。
- volume数据可以持久化保存。
docker提供了两种卷:
- bind mount
- docker managed volume
相同点:
两者都是host文件系统中的某个路径
不同点:
bind mount | docker managed volume | |
---|---|---|
volume位置 | 可任意指定 | /var/lib/doker/volumes/… |
对已有mount point影响 | 隐藏并替换为volume | 原有数据复制到volume |
是否支持单个文件 | 支持 | 不支持,只能是目录 |
权限控制 | 可设置为只读,默认是读写权限 | 无控制,均为读写权限 |
移植性 | 移植性弱,与host path绑定 | 移植性强,无需指定host目录 |
一、实验环境(rhel7.3版本)
1.selinux和firewalld状态为disabled
2.各主机信息如下:
server1(安装好docker) | 172.25.1.1 |
---|---|
server2(安装好docker) | 172.25.1.2 |
二、bind mount卷
是将主机上的目录或文件mount到容器里。
使用直观高效,易于理解。
使用 -v 选项指定路径,格式 <host path>:<container path>
注意:
bind mount 默认权限是读写rw,可以在挂载时指定只读ro,-v选项指定的路径,如果不存在,挂载时会自动创建
示例:
- 创建容器:
[root@server1 ~]# docker run -it --name vm1 -v /tmp/data1:/data1 -v /tmp/data2:/data2:ro -v /etc/yum.repos.d/yum.repo:/yum.repo:ro ubuntu
#data1目录默认权限 data2目录和yum.repo文件设置只读。
- 测试几个目录及文件的权限
三、docker managed volume
docker managed volume
bind mount必须指定host文件系统路径,限制了移植性。
docker managed volume 不需要指定mount源
跨主机的volume就需要使用第三方的驱动:https://docs.docker.com/engine/extend/legacy_plugins/#volume-plugins
- 查看现有管理卷
[root@server1 ~]# docker volume ls
DRIVER VOLUME NAME
local 4984ed1591713db2c8580fc0c58d199969439d8c4b00e1c1b3f2ea1b20e62a8b
- 清除没有容器使用的管理卷
[root@server1 ~]# docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
4984ed1591713db2c8580fc0c58d199969439d8c4b00e1c1b3f2ea1b20e62a8b
Total reclaimed space: 1.106kB
下面的实验会用到registry镜像:
[root@server1 ~]# docker run -d --name registry registry:2
再次查看数据管理卷:发现生成了一个管理卷
[root@server1 ~]# docker volume ls
DRIVER VOLUME NAME
local b578d5f8715b85146555838467ef431c883495ac5477ddf0cec74435335f2156
查看registry的相关信息:
[root@server1 ~]# docker inspect registry
Source为管理卷在宿主机的目录,是docker为容器自动生成的目录,如果挂载时不指定目录,容器内挂载目录的原有数据会复制到宿主机的该目录中。注意,即使删除容器,管理卷也不会删除。
我们会发现,docker自动生成的目录名称会很长,不方便书写使用。我们可以在创建容器时自己定义目录名称。
[root@server1 ~]# docker run -d --name registry -v registry2:/var/lib/registry registry:2
80b2f173dd4772b932fe3c91fcb210b1dcd180b4fbe589a17559674a08545e59
[root@server1 ~]# docker volume ls
DRIVER VOLUME NAME
local registry2
查看管理卷目录:
同样,我们也可以先创建管理卷,再创建目录时指定该目录为容器的管理卷
[root@server1 ~]# docker volume create vol1 #创建名为vol1的管理卷
vol1
[root@server1 ~]# docker volume ls
DRIVER VOLUME NAME
local registry2
local vol1
创建容器并将管理卷挂载到容器内的指定目录:
[root@server1 ~]# docker run -d --name registry2 -v vol1:/var/lib/registry registry:2
d3819888a9b9ae2b346780446e82b4d029874f3d23083b148ea816ba5c81c337
[root@server1 ~]# docker inspect registry2 | grep Source
"Source": "/var/lib/docker/volumes/vol1/_data",
新建管理卷,创建容器时挂载管理卷可以指定目录读写权限:
[root@server1 ~]# docker volume create vol2
vol2
[root@server1 ~]# docker volume ls
DRIVER VOLUME NAME
local registry2
local vol1
local vol2
[root@server1 ~]# docker run -it --name registry3 -v vol2:/data:ro ubuntu
root@8ca9ca09bdc4:/# cd data/
root@8ca9ca09bdc4:/data# touch file
touch: cannot touch 'file': Read-only file system
root@8ca9ca09bdc4:/data# exit
[root@server1 ~]# docker inspect registry3 | grep Source "Source": "/var/lib/docker/volumes/vol2/_data",
四、convoy卷插件
1、首先在server1和server2主机搭建nfs文件系统
server1:
[root@server1 ~]# yum install nfs-utils.x86_64 -y #安装nfs服务对应的软件
[root@server1 ~]# systemctl start rpcbind #启动相关服务
[root@server1 ~]# mkdir /mnt/nfs #创建共享目录
[root@server1 ~]# chmod 777 /mnt/nfs/ #赋予共享目录/mnt/nfs目录777的权限,这步必须做,因为运行容器时,是以普通用户的身份运行的。如果没有写的权限,会报错。
[root@server1 ~]# vim /etc/exports #编写共享目录的文件,这个文件是空的,需要自己填写
/mnt/nfs *(rw,no_root_squash)
[root@server1 ~]# systemctl start nfs
值的注意的是:rpcbind服务必须是开启的。这是因为:他是一个RPC服务,主要是在nfs共享时候负责通知客户端,服务器的nfs端口号的。简单理解rpc就是一个中介服务。
server2:
[root@server2 ~]# yum install -y nfs-utils.x86_64
[root@server2 ~]# systemctl start nfs-server.service #启动nfs服务
[root@server2 ~]# showmount -e 172.25.1.1 #查看server1的共享文件
[root@server2 ~]# mkdir /mnt/nfs #创建目录/mnt/nfs,便于挂载。
[root@server2 ~]# mount 172.25.1.1:/mnt/nfs /mnt/nfs #将172.25.1.1下的/mnt/nfs目录挂载到本地的/mnt/nfs目录下
[root@server2 ~]# df #查看挂载信息,以确保挂载成功
172.25.1.1:/mnt/nfs 17811456 4411904 13399552 25% /mnt/nfs
测试nfs环境是否搭建完成:
#客户端(server2)上touch文件
[root@server2 ~]# cd /mnt/nfs
[root@server2 nfs]# ls
[root@server2 nfs]# touch file #在挂载点/mnt/nfs目录中创建文件file
[root@server2 nfs]# ls
file
#在服务端(server1)上进行查看
[root@server1 ~]# cd /mnt/nfs/
[root@server1 nfs]# ls #可以看到客户端写入的内容,表示nfs服务搭建成功
file
2、配置convoy环境
1、在server1端:下载convoy对应的压缩包(convoy.tar.gz),进行解压,并进行配置
docker官方提供了卷插件的api,在我知道的实现docker卷插件有flocker、convoy这两个插件。开发者可以根据实际需求定制卷插件驱动。
https://docs.docker.com/engine/extend/plugins_volume/#volume-plugin-protocol
[root@server1 ~]# tar zxf convoy.tar.gz
[root@server1 ~]# cd convoy/
[root@server1 convoy]# ls
convoy convoy-pdata_tools SHA1SUMS
[root@server1 convoy]# cp convoy* /usr/local/bin/ #将二进制文件复制到PATH路径下
[root@server1 convoy]# mkdir /etc/docker/plugins #创建docker的卷插件目录
[root@server1 convoy]# convoy daemon --drivers vfs --driver-opts vfs.path=/mnt/nfs &> /dev/null &
#值的注意的是:第一次运行上面的convoy daemon命令的时候,会在/mnt/nfs目录下生成一个config文件夹,这个文件夹不要删除,不然客户端的convoy命令就会用不了
[root@server1 convoy]# cd /mnt/nfs/
[root@server1 nfs]# ls
config
[root@server1 nfs]# echo "unix:///var/run/convoy/convoy.sock" > /etc/docker/plugins/convoy.spec #将convoy守护进程开启生成的.sock文件放入/etc/docker/plugins目录下的convoy.spec文件中,docker就可以识别。(其中convoy.spec文件之前是不存在的)
[root@server1 nfs]# cat /etc/docker/plugins/convoy.spec
unix:///var/run/convoy/convoy.sock
2、创建卷
[root@server1 nfs]# docker volume ls
DRIVER VOLUME NAME
[root@server1 nfs]# convoy create vol1
vol1
[root@server1 nfs]# ll /mnt/nfs/ #可以看到vol1目录
total 0
drwx------ 2 root root 34 May 31 20:56 config
drwx------ 2 root root 6 May 31 20:56 vol1
3、将解压convoy目录给server2复制一份,配置convoy环境
server1:
[root@server1 ~]# scp -r convoy server2:
root@server2's password:
convoy-pdata_tools 100% 22MB 22.0MB/s 00:01
convoy 100% 19MB 19.5MB/s 00:01
SHA1SUMS
server2:
[root@server2 ~]# cd convoy/
[root@server2 convoy]# ls
convoy convoy-pdata_tools SHA1SUMS
[root@server2 convoy]# cp convoy* /usr/local/bin/
[root@server2 convoy]# mkdir /etc/docker/plugins
[root@server2 convoy]# echo "unix:///var/run/convoy/convoy.sock" > /etc/docker/plugins/convoy.spec
[root@server2 convoy]# convoy daemon --drivers vfs --driver-opts vfs.path=/mnt/nfs &> /dev/null &
[1] 2038
3、操作卷
- 列出全部convoy卷:
[root@server2 ~]# convoy list
- 创建卷
[root@server1 nfs]# convoy create vol1
vol1
- 使用卷
[root@server2 ~]# docker run -it --name vm1 -v vol1:/data --volume-driver=convoy ubuntu
root@888d5d2b41c9:/# cd data/
root@888d5d2b41c9:/data# touch file{1..10}
root@888d5d2b41c9:/data# ls
file1 file10 file2 file3 file4 file5 file6 file7 file8 file9
可以在/mnt/nfs/vol1目录查看到文件:
由上可知server1和server2上看到的内容一致,即不同主机间实现了共享存储。
我们在server1上也使用该卷创建容器:
[root@server1 ~]# docker run -it --name vm2 -v vol1:/data --volume-driver=convoy ubuntu
root@aaca9c998d2a:/# cd data/
root@aaca9c998d2a:/data# ls
file1 file10 file2 file3 file4 file5 file6 file7 file8 file9
可以查看到server2上建立的文件。
- 创建卷快照
[root@server1 ~]# convoy snapshot create vol1 --name vol1_pic
vol1_pic
--name前面的是卷名
加个--name起个名字,不然会是数字