Docker存储卷
- 存储卷定义及其分类
- 管理卷
- 绑定卷
-
- [-v 创建绑定卷](#-v 创建绑定卷)
- [- - mount创建绑定卷](#- - mount创建绑定卷)
- 存储卷共享性验证
- 临时卷
-
- [- - tmpfs](#- - tmpfs)
- [- - mount](#- - mount)
- 操作案例
- 扩展问题
存储卷定义及其分类
定义
🚀存储卷就是将宿主机的本地文件系统中的某个目录与容器内部的文件系统中的某个目录建立绑定关系,绑定关系就是当在容器的这个目录下写入数据时会同步到宿主机的这个目录中,同样在宿主机的这个目录下写入数据也会同步到容器的这个目录下,而在宿主机上的这个与容器形成绑定关系的目录就叫作存储卷。
优点
- 防止数据丢失
🚀在容器中存储的数据是存储在联合文件系统的最上层---容器层的,其生命周期是随容器的,也就意味着当容器被删除的时候,这些数据就会被删除掉,如果我们容器中运行的是像MySQL这样的服务,数据丢失将会是比较大的损失。但是,如果容器将这些数据存储在存储卷上,也就是说存储在宿主机的文件系统上,那么即使容器被删除,这些数据也不会丢失。 - 性能较高
🚀在联合文件系统中, 容器能够修改的只有最上层的容器层,当容器想要修改一个文件时,会沿着文件系统向下查找,找到之后拷贝到容器层供容器修改,可见这是效率比低下的,对于存储卷来说容器是直接与宿主机的文件系统进行读写的。 - 实现宿主机和容器间数据共享
🚀每个容器之间,宿主机和容器之间都是独立的,当需要宿主机和容器间实现数据共享时是比较麻烦的,而存储卷恰好的解决了这个问题。 - 实现容器与容器之间的数据共享
🚀当多个容器与同一个宿主机的存储卷进行绑定,那么就可以实现多个容器间的数据共享。
分类
- 管理卷
🚀volume管理卷,默认被映射到宿主机的/var/lib/docker/volumes目录下,只需要指定容器的挂载点是什么,而被绑定到宿主机的哪个目录,是由docker 引擎决定的(建立一个新的空的目录,使用已经存在的目录)。其特点就是用户无法指定存储卷的路径,适合作为临时存储。 - 绑定卷
🚀bind mount绑定存储卷,映射到宿主机的指定路径下,在创建绑定卷的时候要手动指定宿主机上的某个路径与容器内的某个路径建立映射关系。 - 临时卷
🚀tmpfs mount临时数据卷,映射到宿主机的内存中,一旦容器停止,tmpfs也会被移除。
管理卷
指令
docker volume create
bash
docker volume create [OPTIONS] [VOLUME]
# 常用选项
-d : 指定驱动,默认是local
--label : 为存储卷设定标签
docker volume inspect
bash
docker volume inspect [OPTIONS] VOLUME [VOLUME...]
# 常用选项
-f : 指定输出格式 --- 默认json
docker volume ls
bash
docker volume ls [OPTIONS]
# 常用选项
-f : 指定筛选条件
--format : 指定输出格式 --- 默认table
-q : 静默模式,只输出id
docker volume prune
bash
docker volume prune [OPTIONS] # 删除所有本地不使用的匿名卷
# 常用选项
--filter : 筛选条件
-f : 强制删除
-a : 删除所有不适用的存储卷,包括命名卷
docker volume rm
bash
docker volume rm [OPTIONS] VOLUME [VOLUME...]
# 删除某个存储卷
# 常用选项
-f : 强制删除
-v选项
bash
docker run/create -v name:directory[:options] .........
# name:管理卷的名称
# directory:存储卷映射到容器的哪个目录
# options : 选项,如ro表示只读,默认是读写的
-
使用-v选项时管理卷已经存在
-
使用-v选项时管理卷还未创建
如果指定的管理卷不存在,那么docker引擎会创建次管理卷,并将绑定到容器指定目录下的数据同步到此管理卷中
-
宿主机的管理卷和容器指定目录下存在同名文件,最终以宿主机上的为准
--mount选项
bash
docker run/create --mount <key>=<value>,<key>=<value>...
# 常用参数
type : 指定存储卷类型: volume/bind/tmpfs
src : 宿主机上卷的名称
dst : 挂载到容器指定的目录
ro : (readonly)只读/默认为读写
-
使用--mount时管理卷已经存在
-
使用--mount时管理卷还未创建
-
宿主机的管理卷和容器指定目录下存在同名文件,最终以宿主机上的为准
管理卷声明周期验证
🚀将nginx2容器停止掉,观察test-volume4存储卷是否被删除。
🚀证明,管理卷的声明周期不是随容器的,当容器被停止,删除后管理卷仍然存在。
管理卷的共享性验证
🚀将两个nginx容器都绑定到同一个管理卷上,修改宿主机上管理卷中的数据,观察两个容器的变化。
创建两个nginx容器,都绑定到test-volume1的管理卷上。
修改test-volume1管理卷中的index.html内容,在浏览器上分别访问8081/8082端口。
绑定卷
🚀使用-v或者--mount,创建绑定卷与创建管理卷十分类似,稍有不同的是,不再指定宿主机上卷的名称,而是要指定一个完整的路径。
-v 创建绑定卷
bash
docker run/create -v name:directory[:options] .........
# name:管理卷的名称
# directory:存储卷映射到容器的哪个目录
# options : 选项,如ro表示只读,默认是读写的
-
使用-v选项时绑定卷已经存在
与管理卷不同的是,容器启动后并不会将容器目标目录下的文件同步到绑定卷中,而是以宿主机绑定卷中的内容为基准,同步到容器中
-
使用-v选项时绑定卷还未创建
系统会自动创建此绑定卷,并且以该宿主机上绑定卷的内容为基准,同步到容器中
-
绑定卷中与容器目标目录下同名文件问题验证
出现同名文件,以宿主机为准
- - mount创建绑定卷
bash
docker run/create --mount <key>=<value>,<key>=<value>...
# 常用参数
type : 指定存储卷类型: volume/bind/tmpfs
src : 宿主机上卷的名称
dst : 挂载到容器指定的目录
ro : (readonly)只读/默认为读写
-
使用--mount时绑定卷已经存在
与管理卷不同的是,容器启动后并不会将容器目标目录下的文件同步到绑定卷中,而是以宿主机绑定卷中的内容为基准,同步到容器中
-
使用--mount时绑定卷还未创建
对于--mount选项而言,如果绑定卷没有创建,那么就会报错提示此绑定卷不存在。并不会像-v选项一样不存在就创建
-
宿主机的绑定卷中与容器目标目录下同名文件验证
出现同名文件,以宿主机为准
存储卷共享性验证
🚀创建一个绑定卷,挂载到两个nginx容器指定目录下,修改宿主机绑定卷中的内容,观察两个nginx容器变化。
临时卷
🚀临时卷是存在于宿主机的内存上的,所以临时卷与管理卷和绑定卷相比具有局限性:
1.不能实现多个容器共享tmpfs挂载。
2.这个功能只有在Linux操作系统上才能使用。
- - tmpfs
bash
docker run/create --tmpfs directory
# directory:存储卷映射到容器的哪个目录
🚀创建临时卷并启动容器,观察临时卷的声明周期。
临时卷也会覆盖掉容器目录下原有的文件。
添加一个首页。
重启容器,查看首页是否还依然存在。
可以看到之前写的index.html文件已经不存在了,说明容器一旦停止,临时卷就会被清空。
- - mount
bash
--mount <key>=<value>,<key>=<value>
# type : volume/bind/tmpfs
# dst 挂载到容器的指定目录
# tmpfs-size : tmpfs大小限制(单位:字节)
# tmpfs-mode : tmpfs的8进制文件模式。默认为 777
🚀使用--mount创建临时卷与--tmpfs一样,都会覆盖容器目标目录下的内容,并且一旦容器停止那么tmpfs也会被销毁。
🚀当tmpfs-size设置为 2048字节,但是向容器的目标目录下放入一个大于2048字节的文件会有什么事情发生呢?
会报错,提示tmpfs没有充足的空间。
操作案例
🚀启动一个MySQL容器绑定到一个绑定卷上,向数据库中存入一些数据,然后删除掉这个MySQL容器,另外启动一个新的MySQL容器,并绑定到之前的绑定卷上,观察在新的数据库中数据是否依然存在。
1.创建一个MySQL容器,创建一个数据库,一个表,向表中写入两条记录。
2.删除此MySQL容器。
3.启动另一个MySQL容器,同样绑定到mysql1这个绑定卷上,查看这个容器中是否存在之前的插入的两条数据。
扩展问题
- 跨主机使用
docker 存储卷是使用其所在的宿主机上的本地文件系统目录,也就是宿主机有一块磁盘,这块磁盘并没有共享给其他的docker主机,容器在这宿主机上停止或删除,是可以重新再创建的,但是不能调度到其他的主机上,这也是 docker本身没有解决的问题,所以docker存储卷默认就是docker所在主机的本地,但是自己搭建一个共享的NFS来存储docker存储的数据,也可以实现,但是这个过程强依赖于运维人员的能力。 所以未来应用的存储和数据往往分离,越来越多的分布式存储方案出现,如s3系列,nfs 等。
- 启动参数未知
容器有一个问题,一般与进程的启动不太一样,就是容器启动时选项比较多,如果下次再启动时,很容器会忘记它启动时的选项,所以最好有一个文件来保存容器的启动,这就是容器编排工具的作用。
一般情况下,是使用命令来启动操作docker,但是可以通过文件来启动,也就读文件来启动,读所需要的存储卷等,但是它也只是操作一个容器,如果要几十上百个容器操作,就需要专业的容器编排工具
- 复杂场景仍需要运维
对于有状态要持久的集群化组件,如mysql的主从。部署维护一个Mysql主从需要运维知识、经验整合进去才能实现所谓的部署,扩展或缩容,出现问题后修复,必须要了解集群的规模有多大,有多少个主节点,有多少个从节点,主节点上有多少个库,这些都要一清二楚,才能修复故障,这些就强依赖于运维经验 这种复杂的场景往往还是需要人力,很难有完美的工具出现。