容器数据卷——持久化
上面说到容器是一个简易版的linux系统和运行在其中的应用程序,那我们的应用程序产生的数据(比如操作日志、异常日志、数据)也是在容器内的系统中存放的,默认不会做持久化 ,如果有一天鲸鱼(docker)造反了。。。
随着容器的关闭,容器内的数据也会丢失,重新开启的容器不会加载原来的数据(简单说就是容器重新启动又是另外一个实例了)。那对容器内的数据需要持久化到宿主机上就很有必要了 。
容器数据卷的设计目的就是做数据的持久化和容器的数据共享,数据卷完全独立于容器的生命周期,也就是说就算容器 关闭或者删除,数据也不会丢失,简单点就是说将宿主机的目录挂载到容器,应用在容器的数据可以同步在宿主机磁盘上,这样容器内的产生的数据就可以持久化了
docker 的存储机制
CentOS7版本的docker,Storage Driver为: Overlay2
backing filesystem: xfs
dockre使用storage driver管理着镜像层和容器层
如果要避免上面的情况,需要实现数据的持久化——docker提供的另一种机制——Data Volume
Data Volume本质就是允许容器内的数据挂载到宿主机的目录
Data Volume的特点:
- Data Volume 是目录或文件,而非没有格式化的磁盘(块设备)
- 容器可以读写 volume 中的数据
- volume 数据可以被永久的保存,即使使用它的容器已经销毁
PS:因为 volume 实际上是 docker host文件系统的一部分,所以volume的容量取决于文件系统当前未使用的空间,目前还没有方法设置 volume 的容量
Data Volume实现持久化的方式
bind mount
和 docker manager volume
主要的区别就是
- bind mount 可以
指定
宿主机的挂载位置;docker manager volume 固定挂载到/var/lib/docker/volumes
目录下面- 如果后期需要把这个容器打包到别的容器继续运行,bind挂载方式会丢失挂载的目录,docker manager还是会有固定的位置(如下如果自定义的存储名称(t3)也会丢失)
bind mount方式
docker run -it -v /宿主机绝对路径:/容器内的目录 镜像名
给容器只读权限
docker run -it -v /宿主机绝对路径:/容器内的目录:ro 镜像名
[root@docker02 ~]# docker run -it --name dc01 -v /mydatavolume:/datavolumeConrtainer centos:7
挂载单个文件
#dockerhost和容器都要指定出挂载的文件
[root@docker01 ~]# docker run -d --name t4 -P -v /nginx/index.html:/usr/share/nginx/html/index.html nginx:latest
manager volume方式
docker run -itd --name t2 -v /容器内的目录 镜像名
docker run -itd --name t2 -v /usr/share/nginx/html -P nginx
#docker inspect查看
自定义存储名称
# docker run -itd --name t3 -v t3:/容器内的目录 镜像名
# docker run -itd --name t3 -P -v t3:/usr/share/nginx/html nginx
#如果自定义名称后,后续需要打包到别的节点运行会丢失数据
#docker inspect 查看
bind mount和manager volume的 区别
对比如下图
数据卷容器(容器间的共享)—— volumes-from
数据卷容器是什么?
挂载父容器实现数据共享的容器叫做数据卷容器
容器到容器之间实现数据共享,通过挂载父容器实现子子代代继承父容器并且当父容器关闭时,也不会影响其他容器之间共享
如果父容器(dc01)已经做过了持久化,和宿主机实现了共享,那么继承父容器的容器也会都会和宿主机同步共享
[root@docker02 ~]# docker run -it --name dc03 --volumes-from dc01 centos:7
[root@docker02 ~]# docker run -it --name dc04 --volumes-from dc03 centos:7
在dc01写入测试文件
[root@docker02 ~]# docker attach dc01
[root@c51193b259a6 ~]# cd /datavolumeContainer01/
[root@c51193b259a6 datavolumeContainer01]# echo '123.com' > test.txt
在dc03,dc04查看
[root@docker02 ~]# docker attach dc04
[root@99e827c0e722 datavolumeContainer01]# cd /datavolumeContainer01/
[root@99e827c0e722 datavolumeContainer01]# ls
test.txt
[root@99e827c0e722 datavolumeContainer01]# touch update.txt
在宿主机查看
[root@docker02 mydatavolume]# ls
test.txt update.txt
容器的跨主机的共享
环境准备:
服务 | 主机 | 备注 |
---|---|---|
docker01/nginx/nfs | 172.16.46.111 | 挂载节点 |
docker02/nginx/nfs | 172.16.46.112 | 挂载节点 |
nfs | 172.16.46.113 | 数据节点 |
跨主机共享实现思路:
- 都安装nfs服务,保证3台dockerhost外部nfs可以共享目录
- 运行docker容器时挂载目录为dockerhost上的nfs共享目录
- 实现跨主机的共享
nfs实现跨主机的缺点:
太过于依赖nfs服务,nfs服务宕机,所有的docker容器都无法访问
实现跨主机共享
如果docker运行时挂载的数据在其他的节点上,可以实现跨主机共享的方式解决,避免了数据重复拷贝的问题。
安装nfs,都要安装
[root@docker01 ~]# yum -y install rpcbind nfs_utils
#安装完成以后,在docker03部署nfs共享目录
[root@docker03 ~]# mkdir /nfsshare
[root@docker03 ~]# cat /etc/exports
/nfsshare *(rw,sync,no_root_squash)
[root@docker03 ~]# systemctl start rpcbind nfs
[root@docker03 ~]# systemctl enable rpcbind nfs
Created symlink from /etc/systemd/system/multi-user.target.wants/rpcbind.service to /usr/lib/systemd/system/rpcbind.service.
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.
查看nfs的共享目录
[root@docker01 ~]# showmount -e 172.16.46.113
Export list for 172.16.46.113:
/nfsshare *
[root@docker02 ~]# showmount -e 172.16.46.113
Export list for 172.16.46.113:
/nfsshare *
#挂载nfs的共享目录,docker01和docker02都挂载
[root@docker02 ~]# mkdir /nginx
[root@docker02 ~]# mount -t nfs 172.16.46.113:/nfsshare /nginx/
运行容器挂载nginx的目录
[root@docker01 ~]# docker run -d --name t1 -P -v /nginx:/usr/share/nginx/html nginx
8107c13501d3059494bf02df13844d796d417949ce84d227ce02e5b55745c850
[root@docker02 ~]# docker run -d --name t2 -P -v /nginx:/usr/share/nginx/html nginx
6f21376049863de8ca19c7e5d32dff88625c0371ba3540764f1d721c4e5e9119
访问测试
这样就基本实现了夸主机共享的问题,但是,数据节点的服务器存在单点故障的问题。
解决过度依赖nfs服务器的问题
实现的思路:
对于一次的同步得结果使用Dockerfile做成新的nginx镜像,保存到镜像里面,再基于此镜像运行容器,此时,通过Dockerfile里的VOLUME参数把数据持久化宿主机,不在依赖nfs。
PS:在Dockerfile定义VOLUME挂载时 ,默认走的是docker manager volume挂载
缺点:不能实时更新,若经常变动,需要多次手动构建
[root@docker02 ~]# cd /nginx/
[root@docker02 nginx]# ls
Dockerfile index.html
[root@docker02 nginx]# cat Dockerfile
FROM nginx
COPY index.html /usr/share/nginx/html/index.html
VOLUME /usr/share/nginx/html
#构件镜像
docker build -t nfs_nginx .
#基于镜像运行容器
docker run -d --name t6 -P nfs_nginx
[root@docker02 ~]# curl localhost:32771
hahahaha
验证,关掉nfs服务
会发现,其他依赖于nfs服务器的都无法访问,唯独t6
[root@docker02 ~]# curl localhost:32768
^C
[root@docker01 ~]# curl 172.16.46.111:32768
^C^C
docker run -d --name t6 -P nfs_nginx
[root@docker02 ~]# curl localhost:32771
hahahaha