Docker基础(三):容器数据卷


想象一下,你的公司使用docker在容器中部署了一个电商项目,数据全部存在容器中。现在,你一不小心把这个容器删了,里面的数据全没了,再也无法恢复。完了,公司的核心资产被你搞没了,猜猜你能在牢里蹲多久?

啥是数据卷

当然,一个公司业务不可能这么脆弱,但是容器天生就有数据不持久的特点,数据随容器即生即灭,那有什么方法能让其中的重要数据持久化呢?答案就是备份。前面讲过,docker可以通过cp命令和export将容器中的数据备份到主机上,这不失是一种方法。但是,这种操作是一次性的,也即每需要备份时都要手动执行一次,当业务大时,这是不可想象的。那么有没有一种办法,使容器中特定目录和主机之间建立一个持久性的联系,实现自动备份?有的,这就是docker容器数据卷,简称容器卷,或数据卷,或

所谓卷,就是在主机的指定目录和容器内指定目录之间建立一个双向的管道,二者中的数据完全相同,且任意一者的更改都会同步到另一者之中,实现实时备份与数据共享。

数据卷(Data Volumes)是一个可供容器使用的特殊目录,它将主机OS目录直接映射进容器,类似于Linux的mount行为。

​ ■ 数据卷可以在容器之间共享和重用,容器间传递数据将变得高效与方便;

​ ■ 对数据卷内数据的修改会立马生效,无论是容器内操作还是本地操作;

​ ■ 对数据卷的更新不会影响镜像,解耦开应用和数据;

​ ■ 卷会一直存在,直到没有容器使用,可以安全卸载它;


创建数据卷

Docker提供volume子命令来管理数据卷,如下命令可以在本地创建一个名为test的数据卷:

docker volume create -d local test

该数据卷存在本地主机的 /var/lib/docker/volumes 路径下,在该路径下会新建一个名为test的目录,就是创建的数据卷。使用inspect查看卷的信息:

docker voulme inpect test

得到如下结果,

可以看到,Mountpoint值为/var/lib/docker/volumes/test/_data,说明改卷会将选定的容器目录映射进主机的该目录中。如果想要让容器使用该卷,使用run -v test:...来绑定该卷即可。

出来create和inspect,docker volume还支持ls(列出已有数据卷)、prune(清理无用数据卷)、rm(删除数据卷)等,当然这些命令都比较简单。


绑定数据卷

创建完数据卷后,使用run-v(volume)选项来将容器的指定目录绑定上该数据卷,建立容器目录和主机目录之间的双向映射,以数据卷test为例,具体命令为:

docker run -d -v test:/data --name=r3 redits:6.0.8

上述命令将会创建容器r3,并将r3的/data目录映射到主机/var/lib/docker/volumes/test/_data目录中,当对r3的该目录进行操作时,主机也会进行同步。

同样,在主机的对应目录下进行操作,/data也会同步。比如,前者创建一个文件或目录,后者也会跟着创建一个文件或目录,前者对某个文件进行更改,后者的该文件也会相应更新。

现在你肯定想问,能不能不预先创建数据卷,直接在run时创建数据卷,进行目录映射,且指定主机目录?当然可以,依然使用-v选项,以r1的/data目录为例,命令形式为:

docker run -d -v 主机目录:/data --name=r1 redits:6.0.8

也可以用--mount选项来进行绑定。比如,使用 training/webapp 镜像创建 Web 容器,并创建一个数据卷挂载到容器的/opt/webapp 目录:

docker run -d -P --name web --mount type=bind,source=/webapp,destination=/opt/ 
webapp training/webapp python app.py

另外,-v是可以同时创建多个数据卷的,完成多对目录的映射(–mount应该也可以,没试过)。命令形式也很间,用多个-v就行了:

docker run -d -v 主机目录1:容器目录1 -v 主机目录2:容器目录2 --name=r1 redits:6.0.8

这里建议,在使用存储类服务时,一定要记得用数据卷,尤其是mysql这种!在用mysql创建容器时,一般都会将logdataconfig均创建一个数据卷进行备份,因此,创建mysql容器通常用命令:

docker run -p 3307:3306 --name mysql-master \
-v /mydata/mysql-master/log:/var/log/mysql \
-v /mydata/mysql-master/data:/var/lib/mysql \
-v /mydata/mysql-master/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root  \
-d mysql

权限

数据卷有两种权限,一是rw(读写),一是ro(只读)。这里的权限是只针对容器而不针对主机的。比如,rw指容器对主机相应目录可读可写,ro指容器对主机相应目录只能读不能写。

容器使用数据卷的默认权限是rw,如果想要用ro,对命令进行如下更改即可:

docker run -d -v 主机目录:/data:ro --name=r1 redits:6.0.8

注意,当使用ro后,不是指容器内的写操作不会被映射,而是指容器已经无法对该目录(容器内)进行任何写操作了,因为它是一个Read-only file system


数据卷容器

如果你需要在多个容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。数据卷容器也是一个容器,但是它的目的是专门提供数据卷给其他容器挂载。

首先,创建一个容器dbdata,并在其中创建一个数据卷挂载到主机的/dbdata目录下:

docker run -it -v /dbdata:/ --name dbdata ubuntu

然后,可以在其他容器中使用--volumes-from来挂载dbdata容器中的数据卷,例如创建db1和db2两个容器,并从dbdata容器挂载数据卷:

docker run -it --volumes-from dbdata --name db1 ubuntu
docker run -it --volumes-from dbdata --name db2 ubuntu

此时,容器db1和db2都挂载同一个数据卷到相同的/dbdata目录中,三个容器任何一方在该目录下的写入,其他容器都可以看到,当然,主机也能看到。

--volumes-from这个名字就可以看出来,这种关系可以理解为数据卷的继承。既然如此,那么可不可以层层继承?答案是可以的。比如,在上面的基础上,我们可以在创建一个容器db3,它将从db1处继承容器卷,这样一来,四台容器和主机都会互相连通。

docker run -it --volumes-from db1 --name db3 ubuntu

如果删除了”父类“容器(包括dbdata、db1和db2),数据卷并不会被删除,这意味着db3依然能够通过其与主机进行映射,即使其”父类“已经消失了。更好玩的是,当你停止了dbdata、db1和db2(并没有删除),然后在主机相应目录或db3相应目录进行写入,比如创建一个a.txt。然后再打开上面上个容器,它们仍然会同步这些数据,即出现a.txt。


实现原理

我挺好奇数据卷的实现原理的,比如它到底是对多个空间进行相互拷贝还是建立了一个共享空间,又比如它不属于联合文件系统(Union File System)到底是什么意思,这点我还没搞懂,而且也没查到相关的资料。等我搞懂了会补上,如果有大佬知道千万要告诉我,蟹蟹!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值