传送门
docker系列1:docker安装
docker系列2:阿里云镜像加速器
docker系列3:docker镜像基本命令
docker系列4:docker容器基本命令
docker系列5:docker安装nginx
docker系列6:docker安装redis
docker系列7:docker安装ES
docker系列8:容器卷挂载(上)
接着容器卷挂载说起
容器卷管理
前面重点都在讨论容器卷的挂载概念以及如何挂载。容器卷的挂载也同"磁盘挂载"一样,既可以挂载也可以卸载:
umount [-ahnrvV][-t <文件系统类型>][文件系统]
那么容器卷也是一样可以卸载的:
# my-vol为卷名称
docker volume rm my-vol
下面还是以redis为例来验证一把!
容器卷的卸载
创建容器卷
除了前面介绍的启动时自动挂载,还可以手动创建容器卷:
# my-vol为卷名称
docker volume create my-vol
执行一下上面的命令,并查看对应的卷列表:
然后具名挂载到redis上面去:
查看绑定关系:docker inspect test_redis
"Mounts": [
{
"Type": "volume",
"Name": "f81556f7b28978699ef93e996db714980eb6519be7fea5a5acfa4b2dfcc3fec2",
"Source": "/var/lib/docker/volumes/f81556f7b28978699ef93e996db714980eb6519be7fea5a5acfa4b2dfcc3fec2/_data",
"Destination": "/data",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "my-vol",
"Source": "/var/lib/docker/volumes/my-vol/_data",
"Destination": "/usr/etc/redis/data",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
]
那这个时候我们来卸载一下这个绑定关系:docker volume rm my-vol
发现不允许直接删除,那可能会怀疑:如果有正在容器运行的容器使用它就不能直接删除?
那先把这个容器停掉再来删除一下试试:
也不行。那只能把容器删除了再来试试:
成功了!如果有容器挂载了卷,不论容器处于什么状态都不能被直接删除!
卷挂载的方式
不知道你有没有发现一个问题,通过手动创建卷并挂载到容器上。那么这时候在卷目录下创建的文件去哪儿了呢,或者说具体存储在物理机的哪个位置?
先在容器里面创建一个文件my-vol.txt:
现在到宿主机里找一个这个文件my-vol.txt:
而这个目录就是前面查看redis的信息里面挂载对应的目录:
"Mounts": [
{
"Type": "volume",
"Name": "f81556f7b28978699ef93e996db714980eb6519be7fea5a5acfa4b2dfcc3fec2",
"Source": "/var/lib/docker/volumes/f81556f7b28978699ef93e996db714980eb6519be7fea5a5acfa4b2dfcc3fec2/_data",
"Destination": "/data",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "my-vol",
"Source": "/var/lib/docker/volumes/my-vol/_data",
"Destination": "/usr/etc/redis/data",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
]
由此发现容器卷下面的文件都在宿主机上面!
回顾卷挂载的命令:-v 宿主机路径:容器内路径
- 如果是宿主机命令是以"/"开头的绝对路径,就是指定路径挂载,而卷名称就是docker自动生成的,也是匿名挂载的一种特殊形式
- 如果是手动指定了卷名称,这种就是具名挂载
- 还有一种就是不指定宿主机路径,只写了容器内路径,docker也会自动生成卷名称,这种就是匿名挂载
容器卷与容器运行状态的关系
通过上面讨论提到了2个结论:
- 如果有容器挂载了卷,不论容器处于什么状态都不能被直接删除!
- 容器卷下面的文件都在"宿主机"上面!
而对于第2点的"宿主机"要视情况而定,如果是其它外设比如NFS这种,肯定就是网络文件系统里面了。那么如果挂载的卷在运行过程中,由容器产生了很多系统文件(比如服务日志、用户上传的业务文件)会不会由于容器的销毁而丢失呢?
稍微思考一下就会得出一个假设,容器卷内文件与容器的运行状态没有关系!就是不管容器是运行、停止、删除都不会对已有文件产生影响,否则不是违背了持久化的初衷么!
可以在刚才的例子里面验证一把,在my-vol.txt文件里面写入一个"Hello World!":
然后停止容器,在宿主机查看一下该文件内容:
由此可以做一个更大范围的推断,一个卷就算同时被多个容器挂载,也不会因为容器的状态而影响文件内容!
也就是意味着同一个服务多个部署副本可以挂载同一个卷!
在这个在官方的例子中是做为高可用的一种方式:
There are several ways to achieve this when developing your applications. One is to add logic to your application to store files on a cloud object storage system like Amazon S3. Another is to create volumes with a driver that supports writing files to an external storage system like NFS or Amazon S3.
---------------------------------------------- 以下为机译 -----------------------------------------------------
在开发应用程序时,有几种方法可以实现这一点。一种是向应用程序添加逻辑,将文件存储在类似AmazonS3的云对象存储系统上。另一种方法是使用支持将文件写入NFS或AmazonS3等外部存储系统的驱动程序创建卷。
容器卷的读写控制
由于容器卷可以同时被多个容器挂载,有些情况下可能对文件写入就会有区别了:比如控制节点可以写也可以读,从节点可能就不能写了。为此docker也允许在挂载的时候指定容器的读写权限:
回顾卷挂载的命令:-v 宿主机路径:容器内路径:权限
- 在容器内路径后面,接着指定权限
- r-代表读,w-代表写,ro-代表只读(read only),rw-代表可读可写
还是以前面的例子来验证一把,再运行一个容器test_redis2并挂载my-vol卷,指定权限为ro:
现在往my-vol.txt里面写入数据:
通过docker inspect来查看一下的信息:
关于-v与--mount的选择
卷挂载除了通过-v来使用以外还可以通过--mount方式。比如上面的-v my-vol:/usr/etc/redis/data可以替换为--mount source=my-vol,target=/usr/etc/redis/data:
docker run -it --name=test_redis3 --mount source=my-vol,target=/usr/etc/redis/data -v /root/redis/redis.conf:/usr/etc/redis/redis.conf -d redis
通过docker inspect来查看一下的信息:
一样的挂载成功!
关于-v与--mount的选择可以参考Choose the -v or --mount flag