Docker共享存储---共享数据
Docker共享数据
上一篇所说的volume卷就是共享数据的关键,比如web集群,集群每一台节点的数据都要求是相同的,包括之前的一些服务时,也为web集群部署nfs后端来存放数据
bind mount共享数据
学过的bind mount可以用来实现共享数据,但是方法比较笨拙,只能是创建容器的时候指定挂载目录,这样就需要一台一台去进行创建指定
如下:
创建一个要共享的页面目录
[root@localhost ~]# mkdir htdocs/
[root@localhost ~]# vim htdocs/index.html
nihao
然后进行bind mount的方式共享数据
[root@localhost ~]# docker run -d -p 80 --name web --volume /root/htdocs/:/usr/local/apahce2/htdocs httpd
2ac16608128f2ac9462cbded6b0a92b1c210d9c34d7a56278b3b4f6e64e400d9
[root@localhost ~]# docker run -d -p 80 --name web1 --volume /root/htdocs/:/usr/local/apahce2/htdocs httpd
5f2f8214a377541f2c35512bdd241c43d356e32a052bc6a9d683124412b77ea2
[root@localhost ~]# docker run -d -p 80 --name web2 --volume /root/htdocs/:/usr/local/apahce2/htdocs httpd
a51b1477241634d0f66e51c4a7d3d6595128cc30f98c4c70732ed60e6fd92cc8
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a51b14772416 httpd "httpd-foreground" 9 seconds ago Up 8 seconds 0.0.0.0:32770->80/tcp web2
5f2f8214a377 httpd "httpd-foreground" 14 seconds ago Up 14 seconds 0.0.0.0:32769->80/tcp web1
2ac16608128f httpd "httpd-foreground" 25 seconds ago Up 24 seconds 0.0.0.0:32768->80/tcp web
# 分别访问不同容器映射到主机的端口
[root@localhost ~]# curl 192.168.1.11:32770
nihao
[root@localhost ~]# curl 192.168.1.11:32769
nihao
[root@localhost ~]# curl 192.168.1.11:32768
nihao
也可以发现这样确实很麻烦
卷容器共享数据
volume container:专门为其他容器提供volume的容器
volume container既可以通过bind mount共享数据库,也可以通过manage volume来共享数据
我们可以去创建一个卷容器(volume container)名为vc_data,它可以用来指定多个--volume
如下:
[root@localhost ~]# docker create --name vc_data --volume /root/htdocs/:/usr/local/apache2/htdocs \
--volume test:/usr/local/apache2/logs busybox
139ec94bf4cc9dc9198e831ac4ff6e39b166d38c7bda2b3993a35130e59ab975
--volume /root/htdocs/:/usr/local/apache2/htdocs
:将本地的htdocs目录以bind mount方式挂载到容器中的htdocs目录中
--volume test:/usr/local/apache2/logs
:将容器中的logs目录以manage volume的方式映射到物理机本地,volume 名为test
执行完以上命令就会看到一个容器,name为vc_data,这就是我们创建好的volume container。
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
139ec94bf4cc busybox "sh" 4 minutes ago Created vc_data
a51b14772416 httpd "httpd-foreground" 11 minutes ago Up 11 minutes 0.0.0.0:32770->80/tcp web2
5f2f8214a377 httpd "httpd-foreground" 11 minutes ago Up 11 minutes 0.0.0.0:32769->80/tcp web1
2ac16608128f httpd "httpd-foreground" 12 minutes ago Up 12 minutes 0.0.0.0:32768->80/tcp web
查看volume id
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local test
查看容器信息中的挂载信息
[root@localhost ~]# docker inspect vc_data
# 找到以下关键信息
"Mounts": [
{
"Type": "bind", # bind mount 共享数据
"Source": "/root/htdocs",
"Destination": "/usr/local/apache2/htdocs",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "volume", # manage volume共享数据
"Name": "test",
"Source": "/var/lib/docker/volumes/test/_data",
"Destination": "/usr/local/apache2/logs",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
可以看到两种共享数据的方法共存在了vc_data容器中
将volume container被其他容器使用
使用--volumes-from
参数指定volume container(vc_data),可以很大程度避免指定目录时,写错目录名,这些容器都将具有两个挂载类型
[root@localhost ~]# docker run -d -p 80 --volumes-from vc_data --name web3 httpd
0e352478964ac86658db8e72f796bd188f2f269dbdaf41f69816df94c06ee0b7
[root@localhost ~]# docker run -d -p 80 --volumes-from vc_data --name web4 httpd
e966b5860bfd9f063e541791adaeef59b01f4c5595ff7462d5cad3d8ccb1e6bd
[root@localhost ~]# docker run -d -p 80 --volumes-from vc_data --name web5 httpd
390ac7c88206d4c56c1c4dcc7ac9ecda877fcc0587920fe25ffc15a39ef59efc
查看web3/4/5映射端口
[root@localhost ~]# docker ps
PORTS NAMES
0.0.0.0:32773->80/tcp web5
0.0.0.0:32772->80/tcp web4
0.0.0.0:32771->80/tcp web3
0.0.0.0:32770->80/tcp web2
0.0.0.0:32769->80/tcp web1
0.0.0.0:32768->80/tcp web
访问验证
[root@localhost ~]# curl 192.168.1.11:32771
nihao
[root@localhost ~]# curl 192.168.1.11:32772
nihao
[root@localhost ~]# curl 192.168.1.11:32773
nihao
volume container 的特点
- 与 bind mount 相比,不必为每一个容器指定 host path,所有 path 都在 volume container 中定义好了,容器只需与 volume container 关联,实现了容器与 host 的解耦。
- 使用 volume container 的容器其 mount point 是一致的,有利于配置的规范和标准化,但也带来一定的局限,使用时需要综合考虑。
观察起来的话volume container也是有缺点的,就是在物理机中必须存在原始数据。如果要去直接挂载一个空目录来挂载的话,NFS最合适不过了
NFS挂载共享数据
将NFS中的目录共享出去,docker的所有容器来使用这个共享目录就可以了
启动另一台服务器,用来做NFS服务器(192.168.1.12)
192.168.1.12
安装NFS
[root@localhost ~]# yum -y install nfs-utils rpcbind
创建共享目录
[root@localhost ~]# mkdir -p /data/nfs/docker
将目录写入共享文件
[root@localhost ~]# vim /etc/exports
/data/nfs/ *(rw,no_root_squash,sync)
[root@localhost ~]# exportfs -r
[root@localhost ~]# systemctl start rpcbind nfs-server
[root@localhost ~]# systemctl enable rpcbind nfs-server
192.168.1.11
验证共享
[root@localhost ~]# showmount -e 192.168.1.12
Export list for 192.168.1.12:
/data/nfs *
使用docker创建驱动类型为nfs的磁盘volume-nfs,并指定该nfs的ip,共享目录的权限,以及共享目录
[root@localhost ~]# docker volume create --driver local \
--opt type=nfs --opt o=addr=192.168.1.12,rw \
--opt device=:/data/nfs volume-nfs
volume-nfs
# 参数解释
--driver , -d local # 指定卷驱动程序名称,local为默认
--name # 指定卷名
--opt , -o # 设置驱动程序特定选项
查看创建好的volume
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local volume-nfs
查看该volume的信息
[root@localhost ~]# docker volume inspect volume-nfs
[
{
"CreatedAt": "2020-03-31T21:07:36+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/volume-nfs/_data",
# volume-fs的挂载点
"Name": "volume-nfs",
"Options": {
"device": "/data/nfs", # nfs共享目录
"o": "addr=192.168.1.12,rw", # nfs服务器地址
"type": "nfs" # 驱动类型
},
"Scope": "local"
}
]
使用volume-nfs来运行容器
[root@localhost ~]# docker run -itd --name bbox1 --volume volume-nfs:/nfs busybox
[root@localhost ~]# docker exec -it bbox1 /bin/sh
/ # cd /nfs/docker/
/nfs/docker # ls
/nfs/docker # echo "hello world" > 123
/nfs/docker # ls
123
然后查看nfs服务器共享目录的变化(192.168.1.12)
[root@localhost ~]# cd /data/nfs/docker/
[root@localhost docker]# ls
123
同样在nfs创建文件或者目录也会同步到容器中
查看容器挂载点的数据存放的位置的命令
[root@localhost ~]# docker inspect -f {{.Mounts}} bbox1
[{volume volume-nfs /var/lib/docker/volumes/volume-nfs/_data /nfs local z true }]
查看挂载情况
[root@localhost ~]# df -h | grep /data/nfs
:/data/nfs 46G 5.7G 40G 13% /var/lib/docker/volumes/volume-nfs/_data
Dockerfile—VOLUME
data-packed volume container:数据存放到镜像中随便迁移
最后一种共享数据的方法就是,之前有提到过在Dockerfile中的VOLUME可以在构建镜像的时候将物理机的目录挂载到镜像中,使用镜像实例化容器之后,可以直接使用目录中的内容
清空之前实验的容器,方便去查看
编写Dockerfile
[root@localhost ~]# vim Dockerfile
FROM busybox
ADD htdocs /usr/local/apache2/htdocs # 将htdocs中的内容复制到镜像中的指定目录
VOLUME packed /usr/local/apache2/htdocs
# 将镜像中的指定目录以manage volume的方式挂载到物理机中,命名卷名为packed
构建镜像
[root@localhost ~]# docker build -t datapacked /root
Sending build context to Docker daemon 6.9MB
Step 1/3 : FROM busybox
---> 83aa35aa1c79
Step 2/3 : ADD htdocs /usr/local/apache2/htdocs
---> 0a49920ed469
Step 3/3 : VOLUME packed /usr/local/apache2/htdocs
---> Running in 170bb0363ede
Removing intermediate container 170bb0363ede
---> 18031b1fdc1d
Successfully built 18031b1fdc1d
Successfully tagged datapacked:latest
创建一个容器但不运行,使用刚构建的镜像
[root@localhost ~]# docker create --name vc_data datapacked
34ec4accf29c70f4daa2875c35769d30d2ecb5bfe6ce2dd2e8f38a36dc894d1e
再使用httpd镜像实例化容器,也做到了共享资源
[root@localhost ~]# docker run -d -p 80:80 --volumes-from vc_data httpd
9a0705b631dc8e785dc43b9eece8d4feb792b0a367aa7bfd6d8ce5966db75521
[root@localhost ~]# curl 192.168.1.11
nihao
共享数据方法总结
bind mount:从物理机挂载到容器内
managed volume:从容器内挂载到物理机的volume
volume container:创建一个容器,在创建的时候可以使用bind mount也可以使用managed volume,其他容器使用时,可以使用-
-volumes-from
来使用该volume container
NFS:共享目录,在docker中创建volume并挂载共享目录,然后运行的容器使用
--volume
指定该卷即可Dockerfile:将数据使用VOLUME写入到镜像中,然后迁移数据时,直接pull下载镜像就可以运行容器使用以前的数据了