首页 > 其他分享 >Docker:存储卷

Docker:存储卷

时间:2024-10-30 21:48:51浏览次数:7  
标签:容器 存储 宿主机 volume html Docker docker

Docker:存储卷


存储卷

Docker中,容器的文件存储结构如下:

在这里插入图片描述

容器时基于镜像产生的,一个镜像可以实例化出多个容器,为了节省镜像的存储消耗,并不是每个容器都会拷贝一份镜像,而是所有容器共用一份镜像。

为此,Docker采用联合文件系统来存储文件,在镜像内部,所有文件分为多层存储,每个容器创建时,创建一个容器层,在容器层内部修改文件,不会影响镜像。

比如说容器删除一个文件,容器不会去镜像内部删除镜像的某一层,而是新开一层标记某个文件已经删除

在这里插入图片描述

上图中,容器删除了镜像中的文件,但是其实log.txt没有真的被删除,只是对于这个容器来说,被标记为删除了,其他容器依然可以看到log.txt

这种存储结构,可以减少很多的存储损耗,但是任何事物都有两面性,没有完美的解决方案。

  1. 持久化:如果容器被删除,那么整个容器层都直接销毁,数据无法持久化保存到操作系统
  2. 性能:每次容器读写,都要经过联合文件系统,性能极大降低

为此,Docker提供了另一种存储方式存储卷,用于存储需要持久化,或者IO频率高,对性能有要求的文件。

在这里插入图片描述

存储卷可以绕过联合文件系统,直接读写操作系统的文件系统。因为绕过联合文件系统,所以IO效率可以显著提高,另一方面,这些数据并不存储在容器层,而是存储在操作系统,就算容器被删除,容器层被销毁,存储卷也不会被销毁,可以持久化保存。

对于联合文件系统的更多详细信息,会在其他博客有专门讲解,本博客不再深入联合文件系统。


命令

docker volume ls

  • 功能:列出存储卷

语法:

docker volume ls [option]

选项:

  • -f:依据条件过滤
  • -q:仅显示名称

示例:

在这里插入图片描述

此处有三个存储卷,其中my_volume是有名称的,而前两个是没有名称的。DRIVER这一栏,是卷的存储驱动,绝大部分存储卷的驱动都是local,其可以满足大部分场景的需求。

如果加上-q选项,不会显示DRIVER这一列,只显示名称。

使用-f进行过滤:

在这里插入图片描述

-f可以对查询进行过滤,并且支持正则表达式,例如-f name=my*表示查询卷名以my开头的存储卷。

=


docker volume create

  • 功能:创建存储卷

语法:

docker volume create [option] [volume]

选项:

  • -d --driver:指定驱动,默认为local
  • --label:指定元数据

创建一个匿名存储卷:

在这里插入图片描述

创建卷时,如果不指定名称,那么创建的卷就是没有名字的匿名卷。

创建命名卷:

在这里插入图片描述

如果需要命名,那么命令的最后一个参数就是卷名。

指定元数据:

在这里插入图片描述

创建卷时,可以通过--label指定元数据,以键值对的形式。元数据可以帮助快速查询容器,比如通过-f选项可以指定元数据。


docker volume inspect

  • 功能:查看存储卷的详细信息

语法:

docker volume inspect [option] volume

在这里插入图片描述

此处test_vm_2的信息中,可以看到刚才指定的元数据TEST=2,以及卷名,存储驱动等等。


docker volume rm

  • 功能:删除存储卷

语法:

docker volume rm [option] volume [volume...]

选项:

  • -f:强制删除

对于有卷名的存储卷,可以通过卷名删除,如果是匿名的,只能复制一大串随机字符串来指定删除。

如果这个卷正在被容器使用,那么无法直接删除,此时需要通过-f强制删除。


docker volume prune

  • 功能:删除所有不使用的匿名存储卷

语法:

docker volume prune [option]

选项:

  • -f:强制删除

在这里插入图片描述

第一次查询,主机中有三个匿名卷,通过prune删除后,所有匿名卷都被删除了。过程中会进行一次确认[y/N],使用-f参数,则不会进行这次确认。


分类

以上所有操作,都没有把存储卷和容器关联起来,其实存储卷分为三种类型,不同的存储卷创建方式不同。

  • 数据卷:默认映射到宿主机的/var/lib/docker/volumes目录下,只需要在容器内部指定挂载点,而在宿主机的挂载点,docker自动完成
  • 绑定卷:由用户自己指定宿主机的一个文件或目录,共享到容器中
  • 临时卷:前两者在容器销毁后,都可以持久化保存。但是临时卷并不会持久化保存,容器删除后临时卷也会销毁。主要用于高性能IO存储临时数据的场景。

创建以上三种卷,主要在docker run运行容器时,通过-v或者--mount选项进行指定。

数据卷

-v语法:

docker run -v name:directory[:option]

参数:

  • name:绑定的现有卷的名称,可以省略,此时会创建一个新的匿名卷
  • directory:数据卷在容器内部的路径
  • option:可以指定ro表示read only,此时只有宿主机可以修改数据卷,容器只读

后续操作,都基于nginx镜像,在nginx镜像内部,路径/usr/share/nginx/html存放着ngxin的首页文件,以该目录为存储卷位置。

使用现有卷test_vm_1作为数据卷:

在这里插入图片描述

通过-v test_vm_1:/usr/share/nginx/html,表示把存储卷test_vm_1这个存储卷,挂载到容器的/usr/share/nginx/html路径下。

随后查询test_vm_1,找到其在宿主机的存储路径,该路径下多出两个文件50x.htmlindex.html,这就是nginx内部创建的文件,通过数据卷共享到宿主机了。

在这里插入图片描述

就算删除掉这个容器,存储卷内的内容依然存在。

创建匿名数据卷:

在这里插入图片描述

如果容器创建时,只指定挂载路径,但是没有指定存储卷名,那么就会创建一个匿名卷。以上例子中,创建了一个fb48...的匿名卷,进入其存储目录后,也出现了两个共享的html文件。

另外的,如果指定存储卷名时,存储卷不存在,那么也会自动创建一个新的命名卷。

--mount语法:

docker run --mount key=value [key=value ...]

参数:

  • type:存储卷类型,指定volume表示数据卷
  • stc:对于命名卷,表示卷名,对于匿名卷,此字段省略
  • dst:文件在容器的挂载路径
  • ro:只读方式挂载

多个参数以逗号,分隔。

通过--volume创建一个命名卷:

在这里插入图片描述

存储卷挂载命令如下:

--mount type=volume,src=test_vm_3,dst=/usr/share/nginx/html,ro

其中type=volume表示使用数据卷,src=test_vm_3表示使用的存储卷,dst=/usr/share/nginx/html指定容器中的挂载路径,ro表示只读,容器内部无法修改该文件。

进入容器内部修改文件:

在这里插入图片描述

通过docker exec进入容器后,尝试修改存储卷挂载的目录,此时提示Read-only file system,即这个容器对该目录只读,没有权限进行写入。

不论是-v还是--volume效果是一样的。


绑定卷

对于先前的数据卷,在宿主机的存储路径都是由Docker指定的,如果想要把宿主机的指定文件作为存储卷,共享到容器,就需要绑定卷

-v语法:

docker run -v path:directory[:option]
  • name:绑定卷在宿主机的路径
  • directory:绑定卷在容器内部的路径
  • option:可以指定ro表示read only,此时只有宿主机可以修改绑定卷,容器只读

除了path这个参数,其它的和数据卷相同。在数据卷中,使用name:来指派一个存储卷,或者不填写该选项,直接创建一个匿名卷。如果填入的是一个有效的宿主机路径path:,那么就会把宿主机的指定目录或文件,作为绑定卷与容器共享。

nginx容器创建一个绑定卷:

在这里插入图片描述

首先在当前目录创建一个index.html文件写入hello world,随后将该文件绑定到容器中,命令:

-v ./index.html:/usr/share/nginx/html/index.html

此处./index.html是一个有效的本机路径,/usr/share/nginx/html/index.html是容器内部的挂载点。与先前不同,先前指定的是.../html/这个目录,这次指定的是一个具体的.html文件,存储卷既可以共享目录,也可以共享文件。

随后通过docker exec进入容器,查看index.html,发现其内容是hello world。按理来说nginx的这个文件应该初始化为一个有效的html文件,但是最后被宿主机绑定卷的内容给覆盖了。这就是绑定卷与数据卷的区别之一。

绑定卷会把宿主机的文件覆盖容器的文件,哪怕容器的文件原先就有内容。如果宿主机中,绑定卷的内容为空,那么会把容器中的文件也覆盖为空,这会导致一定的数据丢失。但是对于数据卷来说,如果宿主机中内容为空,宿主机会把容器的内容拷贝到宿主机。

之前就可以看出,在数据卷中,把容器内部的50x.htmlindex.html拷贝到宿主机了。但是如果让绑定卷也绑定这个目录,那么宿主机不仅不会拷贝50x.htmlindex.html,还会删掉容器内部的50x.htmlindex.html

绑定卷创建完成后,宿主机和容器内部的文件就同步了,虽然刚创建时宿主机的文件优先级高,但是创建完成后,容器与宿主机对这个文件的操作权限是相同的,只要不指定readonly

--volume语法:

docker run --mount key=value [key=value ...]

参数:

  • type:存储卷类型,指定bind表示绑定卷
  • stc:宿主机的有效路径
  • dst:文件在容器的挂载路径
  • ro:只读方式挂载

多个参数以逗号,分隔。此处的type与数据卷不同,数据卷type=volume,绑定卷type=bind

通过--volume创建一个绑定卷:

在这里插入图片描述

绑定卷命令:

--mount type=bind,src=./html,dst=/usr/share/nginx/html

把宿主机的./html目录,绑定到容器的/usr/share/nginx/html目录中。ls查看宿主机的./html目录,发现内容为空,进入容器后查看/usr/share/nginx/html目录,依然为空。

原先这个目录应该有两个html文件,但是由于宿主机绑定卷目录为空,所以这两个文件被覆盖删除了。

另外的,绑定卷是无法通过docker volume ls进行查询的。但是可以在容器中查询到,通过docker inspect

在这里插入图片描述

mounts这一栏,可以看到存储卷的信息,类型为绑定卷bind,宿主机目录source,容器目录Destination"RW": true表示可读写。


临时卷

存储卷有两个功能,一个是进行持久化的保存,另一个是进行高效的IO。有的时候只需要高效IO,并不需要持久化,那么就可以使用临时卷。

临时卷为了进一步提高IO效率,对文件存储进行了进一步优化。数据卷和绑定卷都是存储在硬盘中的,但是临时卷存储在内存中,是一个内存级的文件,IO效率极高。但是由于内存不是持久化存储的,所以临时卷在容器停止时就会销毁,注意是停止stop时,而不是删除rm时。

注意点:

  1. 临时卷是Linux专有的,Windows等其它操作系统上的Docker,无法使用临时卷。
  2. 临时卷只能挂载目录,不能挂载文件

--tmpfs语法:

docker run --tmpfs path

只需要指定容器中的一个目录为临时卷即可,由于并不于主机互通,无需指定主机路径或者卷名。

创建一个临时卷:

在这里插入图片描述

此处把/usr/share/nginx/html目录指定为了临时卷,进入目录后,原先存在的两个html文件也被覆盖了,说明临时卷也会清空目录内的原有内容。

--mount语法:

docker run --mount key=value [key=value ...]

参数:

  • type:存储卷类型,指定tmpfs表示临时卷
  • dst:文件在容器的挂载路径
  • tmpfs-size:临时卷的限制大小
  • tmpfs-mode:挂载模式,以八进制形式指定目录权限,默认为1777

创建一个内存限制不超过1m的临时卷:

在这里插入图片描述

临时卷命令:

--mount type=tmpfs,dst=/usr/share/nginx/html,tmpfs-size=1m

进入容器后,创建一个5m的文件index.html

dd if=/dev/zero of=index.html bs=1M count=5

此处的dd命令,用于创建一个5m的空文件。

显示dd: error writing 'index.html': No space left on device表示创建失败,没有空间了。因为限制了临时卷最多使用1m,此处却创建了5m的文件。

最后通过ls -l查看文件,发现index.html的大小是1048576,也就是1024 * 1024 byte = 1m


标签:容器,存储,宿主机,volume,html,Docker,docker
From: https://blog.csdn.net/fsdfafsdsd/article/details/143318362

相关文章

  • Docker 自建 Registry
    如果你需要保存自己的镜像,但又不想直接公开出来,那么可以选择自建Registry.如果想要加速国内访问,可以选择自建DockerProxy,或者使用https://dockerproxy.net.本文发表于https://clouder0.com/zh-cn/posts/docker-registry-self-host/.需要把我自己打包的image部署出来,自......
  • 不使用docker-compose不使用zookeeper启动ApacheKafka3.8.0单机运行KRAFT模式
    dockerrun-d-v/kafka_data:/opt/kafka-logs-eKAFKA_ENABLE_KRAFT=yes-eKAFKA_PROCESS_ROLES=broker,controller-eKAFKANODEID=1-eKAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093-eKAFKA_ADVERTISED_LISTENERS=PLAINTEXT://192.1......
  • MySQL存储引擎——针对实习面试
    目录MySQL支持哪些存储引擎?MySQL存储引擎架构了解嘛?MyISAM和InnoDB有什么区别?MyISAM和InnoDB如何选择?如何查看表的存储引擎?如何修改表的存储引擎?MySQL支持哪些存储引擎?MySQL支持多种存储引擎,包括InnoDB、MyISAM、MEMORY、ARCHIVE、BLACKHOLE、FEDERATED、NDBCluste......
  • 【Docker】bridge的基础使用和测试
    参考Bridgenetworkdriver|DockerDocsdockernetwork|DockerDocs命令Usage:dockernetworkCOMMANDManagenetworksCommands:connectConnectacontainertoanetworkcreateCreateanetworkdisconnectDisconnectacontainerfro......
  • 数据库之存储过程
    存储过程一、存储过程介绍1、什么是存储过程?存储过程是实现某个特定功能的sql语句的集合,编译后的存储过程会保存在数据库中,通过存储过程的名称反复的调用执行。2、存储过程的优点?(1)存储过程创建后,就可以反复的调用和使用,不需要重新写复杂的语句(2)创建,修改存储过程不会对数据有......
  • InnoDB 存储引擎<四>磁盘文件一
    目录磁盘文件系统表空间-SystemTablespace 独⽴表空间-File-Per-TableTablespace  撤销表空间-UndoTablespaces磁盘文件1.InnoDB存储引擎包含哪些磁盘⽂件?分析过程:从官⽹给出的InnoDB架构图中可以找到答案InnoDB存储引擎架构链接解答问题:......
  • 【Docker】Dockerfile 指令对 Docker 镜像层数的影响
    本文内容均来自个人笔记并重新梳理,如有错误欢迎指正!如果对您有帮助,烦请点赞、关注、转发、订阅专栏!专栏订阅入口| 精选文章 | Kubernetes |Docker|Linux |羊毛资源 | 工具推荐 |往期精彩文章【Docker】(全网首发)KylinV10下MySQL容器内存占用异常的解决......
  • Docker快速部署snipeit(Mac机)
    前提安装好mysql和docker环境(很多地方需要db统一的方便管理)官方操作手册1.拉取配置文件curlhttps://raw.githubusercontent.com/snipe/snipe-it/master/docker-compose.yml--outputdocker-compose.ymlcurlhttps://raw.githubusercontent.com/snipe/snipe-it/master/.env.......
  • 【GiraKoo】线程本地存储(Thread Local Storage, TLS)
    【技术分享】线程本地存储(ThreadLocalStorage,TLS)在项目开发中,遇到了关于TLS相关的问题。为了了解该机制的用途,在微软的官网查找了一些资料。本文参考官方文档,简单介绍一下TLS的用途与使用方法。微软官方文档链接一、简介线程本地存储(TLS),可以使多个线程,通过TlsGetValue函......
  • WD MYbook存储硬盘数据恢复
    WDMYBOOK存储硬盘数据恢复是一个相对复杂但可行的过程,以下是一些建议的恢复方法:一、硬件检查与恢复检查连接线:重新插拔连接线,确保连接稳固且没有损坏。如果连接线有问题,尝试更换一条新的连接线。2.更换电脑设备:如果在一个电脑上无法识别移动硬盘,可以尝试将其连接到另一台电......