Docker系列03—Docker 存储卷
一、存储卷介绍
1.1 背景
Docker 的 AFUS 分层文件系统
docker镜像由多个只读层叠加而成,启动容器时,docker会加载只读镜像层并在镜像栈顶部加一个读写层;
如果运行的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件版本任然存在,只是已经被读写层中该文件的副本所隐藏,此即“写时复制(COW)”机制。
示意图
描述:如果一个文件在最底层是可见的,如果在layer1上标记为删除,最高的层是用户看到的layer2的层,处于layer0上的文件,在layer2上可以删除,但是只标记删除,用户是不可见的,总之在到达最顶层之前,把它标记删除,对于最上层的用户是不可见的,当标记一删除,只有在最上层建一个同名一样的文件,才是可见的。
1.2 为什么要使用存储卷
对于这类操作,修改删除等,一般效率比较低,如果对于I/O要求比较高的应用,如redis在实现持久化存储时,是在底层存储时的性能要求比较高。
假设底层运行一个存储库mysql,mysql本来对于I/O的要求就比较高,如果mysql又是运行在容器中自己的文件系统之上时,也就是容器在停止时,就意味着删除,除非现数据存取效率比较低,要避免这个限制要使用存储卷来实现。
存在的问题:
存储于联合文件系统中,不宜于宿主机访问;
容器间数据共享不便
删除容器其数据会丢失
1.3 存储卷
“卷”是容器上的一个或多个“目录”,此类目录可绕过联合文件系统,与宿主机上的某个目录“绑定(关联)”;
类似于挂载一样,宿主机的/data/web目录与容器中的/container/data/web目录绑定,然后容器中的进程向这个目录中写数据时,是直接写在宿主机的目录上的,绕过容器文件系统与宿主机的文件系统建立关联关系,使得可以在宿主机和容器内共享数据库内容,让容器直接访问宿主机中的内容,也可以在宿主机向容器供给内容,两者是同步的。
在宿主机上能够被共享的目录(可以是文件)被称为volume。
存储卷作用
优点:容器中进程生成的数据,都保存在存储卷上,从而脱离容器文件系统自身后,当容器被关闭甚至被删除时,都不用担心数据被丢失,实现数据可脱离容器生命周期而持久,当再次重建容器时,如果可以让它使用到或者关联到同一个存储卷上时,再创建容器,容器不是之前的容器,但是数据还是之前的数据。特别类似于进程的运行逻辑,进程本身不保存任何的数据,数据都在进程之外的文件系统上,或是专业的存储服务上,所以进程每次停止,只是保存程序文件,对于容器也是一样;容器就是一个有生命周期的动态对象来使用,容器关闭就是容器删除的时候,但是它底层的镜像文件还是存在的,可以基于镜像再重新启动容器。
但是容器有一个问题,一般与进程的启动不太一样,就是容器启动时选项比较多,如果下次再启动时,很容器会忘记它启动时的选项,所以最好有一个文件来保存容器的启动,这就是容器编排工具的作用。一般情况下,是使用命令来启动操作docker,但是可以通过文件来读,也就读文件来启动,读所需要的存储卷等,但是它也只是操作一个容器,这也是需要专业的容器编排工具的原因。
另一个优势就是容器就可以不置于启动在那台主机上了,如几台主机后面挂载一个NFS,在各自主机上创建容器,而容器上通过关联到宿主机的某个目录上,而这个目录也是NFS所挂载的目录中,这样容器如果停止或者是删除都可以不限制于只能在原先的宿主机上启动才可以,可以实现全集群范围内调试容器使用,当再分配存储、计算资源时,就不会再局限于单机之上,可以在集群范围内建立起来,基本各种docker的编排工具都能实现此功能,但是后面严重依赖于共享存储的使用。
1.4 存储卷原理
volume于容器初始化之时会创建,由base image提供的卷中的数据会于此期间完成复制
volume的初意是独立于容器的生命周期实现数据持久化,因此删除容器之时既不会删除卷,也不会对哪怕未被引用的卷做垃圾回收操作
卷为docker提供了独立于容器的数据管理机制
1.5 存储卷分类
Docker有两种类型的卷,每种类型都在容器中存在一个挂载点,但其在宿主机上位置有所不同;
Bind mount volume (绑定挂载卷):在宿主机上的路径要人工的指定一个特定的路径,在容器中也需要指定一个特定的路径。关联两个路径
Docker-managed volume (docker管理卷):只需要在容器内指定容器的挂载点是什么,而被绑定的宿主机下的那个目录,是由容器引擎daemon自行创建一个空的目录,或者使用一个已经存在的目录,与存储卷建立存储关系,这种方式极大解脱用户在使用卷时的耦合关系,缺陷是用户无法指定那些使用目录,临时存储比较适合。
二、使用存储卷
为 docker run 命令使用 -v 选项即可使用 volume
Bind-mount volume (绑定挂载卷):
[root@docker ~]# docker run -d -it --name busybox01 -v /data/busybox:/data busybox:latest
# 宿主机目录:容器目录
# 将容器里面的/data目录挂载到宿主机的/data/busybox目录 [root@docker ~]# docker inspect -f {{.Mounts}} busybox01
[{bind /data/busybox /data true rprivate}]
# 查看挂载情况
Docker-managed volume (docker管理卷)
[root@docker ~]# docker run -d -it --name busybox_2 -v /data/busybox_m busybox:latest
# 容器目录
[root@docker ~]# docker inspect -f {{.Mounts}} busybox_2
[{volume b670ec29f1d5066605e11be7732162687049178b9995195e4e42abe5ba9a7e12 /var/lib/docker/volumes/b670ec29f1d5066605e11be7732162687049178b9995195e4e42abe5ba9a7e12/_data /data/busybox_m local true }]
两者在容器被删除后,文件依旧保存
2.1 使用 Bind-mount volume (绑定挂载卷)
创建容器busybox01
[root@docker ~]# docker run -d -it --name busybox01 -v /data/volumes/busybox01:/data busybox:latest # 注:要是宿主机的目录不存在,则创建
查询存储卷信息
[root@docker ~]# docker inspect -f {{.Mounts}} busybox01
[{bind /data/volumes/busybox01 /data true rprivate}]
在宿主机的存储卷上进行简单的操作
[root@docker ~]# echo "This is a test for delete 01" > /data/volumes/busybox01/index.html
进入容器验证
[root@docker ~]# docker exec -it busybox01 /bin/sh
/ # cat /data/index.html
This is a test for delete 01
5. 验证数据持久性
删除容器,启动新容器,挂载原目录
[root@docker ~]# docker rm -f busybox01
busybox01
[root@docker ~]# docker run -d -it --name busybox01.1 -v /data/volumes/busybox01:/data busybox:latest
[root@docker ~]# docker exec -it busybox01.1 /bin/sh
/ # cat /data/index.html
This is a test for delete 01
6. 多个容器同时关联同一个宿主机目录
[root@docker ~]# docker run -d -it --name busybox02 -v /data/volumes/busybox01:/data busybox:latest
[root@docker ~]# docker exec -it busybox02 /bin/sh
/ # cat /data/index.html
This is a test for delete 01
7. 在宿主机中修该文件内容
[root@docker ~]# echo "This is a test for insert" >> /data/volumes/busybox01/index.html
[root@docker ~]# docker exec -it busybox02 /bin/sh
/ # cat /data/index.html
This is a test for delete 01
This is a test for insert
2.2 使用docker-managed volume (docker管理卷)
创建容器 busybox10
[root@docker ~]# docker run -d -it --name busybox10 -v /data busybox:latest
2. 查看存储卷情况
[root@docker ~]# docker inspect busybox10 # 查询全部
[
{
"Id": "a19a7b24863ead76c5be3d13ec11c2399bb725579b3b8d06422d5eeb5579d307",
"Created": "2020-04-02T11:36:11.917365309Z",
"Path": "sh",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 30402,
"ExitCode": 0,
"Error": "",
"StartedAt": "2020-04-02T11:36:12.119386651Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:83aa35aa1c79e4b6957e018da6e322bfca92bf3b4696a211b42502543c242d6f",
"ResolvConfPath": "/var/lib/docker/containers/a19a7b24863ead76c5be3d13ec11c2399bb72
..................................
[root@docker ~]# docker inspect -f {{.Mounts}} busybox10
# 精确查询
[{volume 4b908787e981e0481cf9f5a520275c1467f662ffb3957f3d15d8e46d8b9b2b43 /var/lib/docker/volumes/4b908787e981e0481cf9f5a520275c1467f662ffb3957f3d15d8e46d8b9b2b43/_data /data local true }]
3. 在宿主机的存储卷目录添加内容
[root@docker ~]# echo "This is a test for mount" > /var/lib/docker/volumes/4b908787e981e0481cf9f5a520275c1467f662ffb3957f3d15d8e46d8b9b2b43/_data/index.html
4. 进入容器验证,并修改文件内容
[root@docker ~]# docker exec -it busybox10 /bin/sh
/ # cat /data/index.html
This is a test for mount
/ # echo "yes" >> /data/index.html
5. 在宿主机上验证
[root@docker ~]# cat /var/lib/docker/volumes/4b908787e981e0481cf9f5a520275c1467f662ffb3957f3d15d8e46d8b9b2b43/_data/index.html
This is a test for mount
yes
2.3 volumes-from 基于已有容器的存储器,创建容器
1. 先创建一个容器
[root@docker ~]# docker run -d -it --name busybox -v /data/volumes/busybox:/data/busybox busybox:latest
[root@docker ~]# docker exec -it busybox /bin/sh
/ # echo " T=T " > /data/busybox/index.html
2. 基于原有的容器启动
[root@docker ~]# docker run -d -it --name busybox_mount --network container:busybox --volumes-from busybox busybox:latest
[root@docker ~]# docker exec -it busybox_mount /bin/sh
/ # cat /data/busybox/index.html
T=T
3. 查看挂载信息
[root@docker ~]# docker inspect -f {{.Mounts}} busybox_mount
[{ /data/volumes/busybox /data/busybox true rprivate}]
三、Volume 删除和孤单 volume 清理
3.1 在删除容器时删除volume
A. Bind-mount volume (绑定挂载卷)
可以使用docker rm -v 命令在删除容器时删除该容器的卷
1. 创建新的容器
[root@docker ~]# docker run -d -it --name busybox_01 -v /data/volumes/del_mount/busybox_01:/data/ busybox:latest
7f5a6cab30ecc04a11c1a77a6a337d72732e164711a41d288f24f3079f063b76
[root@docker ~]# echo "this is a test" > /data/volumes/del_mount/busybox_01/index.html
[root@docker ~]# docker exec -it busybox_01 /bin/sh
/ # cat /data/index.html
this is a test
2. 使用docker rm -v 删除容器及卷
[root@docker ~]# docker stop busybox_01 # 先停止容器
[root@docker ~]# docker rm -v busybox_01
busybox_01
[root@docker ~]# cat /data/volumes/del_mount/busybox_01/index.html
this is a test
?????唉,气不气,绑定挂载卷没有用 #_#
B. docker-managed volume (docker管理卷)
1. 创建容器
[root@docker ~]# docker run -d -it --name busybox_02 -v /data/ busybox:latest
792f5303302264dba913c7c1b6d81ebd59a3db695835a9f1a8be97c0ca0f70bc
[root@docker ~]# docker volume ls
DRIVER VOLUME NAME
local d19467ea5a0c3428d2e77b414607775b17ac2071805cf5501f81bec81d3d1609
local ac2071805d1609cf5501f81becd19467ea5a0c3428d2e77b414607775b1781d3
[root@docker ~]# docker stop busybox_02
web2
[root@docker ~]# docker rm -v busybox_02
web2
[root@docker ~]# docker volume ls
DRIVER VOLUME NAME
local ac2071805d1609cf5501f81becd19467ea5a0c3428d2e77b414607775b1781d3
3.2 批量删除孤单的volumes
[root@docker ~]# docker volume rm $(docker volume ls -qf dangling=true)
# docker volume rm 名称 为删除某一个volume
# docker volume ls -qf dangling=true 列举孤单的volume
[root@docker ~]# docker volume ls
DRIVER VOLUME NAME
四、总结
卷有两种,两种,两种,两种,,,,
挂载卷-管理卷
Docker系列03—Docker 存储卷的更多相关文章
- Docker系列03—Docker 基础入门
本文收录在容器技术学习系列文章总目录 1.概念介绍 1.1 容器 1.1.1 介绍 容纳其它物品的工具,可以部分或完全封闭,被用于容纳.储存.运输物品.物体可以被放置在容器中,而容器则可以保护内容物. ...
- Docker系列05—Docker 存储卷详解
本文收录在容器技术学习系列文章总目录 1.存储卷介绍 1.1 背景 (1)docker 的 AFUS 分层文件系统 docker镜像由多个只读层叠加面成,启动容器时,docker会加载只读镜像层并在镜 ...
- Docker系列教程05-Docker数据卷(Data Volume)学习
引言 在Docker中,容器的数据读写默认发生在容器的存储层,当容器被删除时其上的数据将会丢失.要想实现数据的持久化,需要将数据从宿主机挂载到容器中.目前Docker提供了三种方式将数据从宿主机挂载到 ...
- Docker系列01—Docker 基础入门
一.初识Docker和容器 1.1 什么是docker 容纳其他物品的工具,可以部分或完全封闭,被用于容纳.存储.运输物品.物体可以被放置在容器中,而容器则可以保护内容物. 容器? 容器就是在隔离的环 ...
- Docker系列之Docker镜像(读书笔记)
一.基本概念 Docker包括三个基本概念镜像.容器.仓库. Docker镜像:就是一个只读的模板.例如:一个镜像可以包含一个完整的ubuntu操作系统环境,里面仅安装了Apache或其他应用程序.用 ...
- docker 系列之 docker安装
Docker支持以下的CentOS版本 CentOS 7 (64-bit) CentOS 6.5 (64-bit) 或更高的版本 前提条件 目前,CentOS 仅发行版本中的内核支持 Docker. ...
- Docker系列二: docker常用命令总结
https://docs.docker.com/reference/ 官方命令总结地址 容器生命周期管理 1.docker run 创建一个新的容器并运行一个命令 docker run [optio ...
- Docker系列一: docker简介及基本环境安装
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源. Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布到任何流行的 Li ...
- docker系列之六容器数据卷
docker之容器数据卷 一.容器数据卷 docker容器运行的时候,会产生一系列的文件,那么我们希望容器产生的数据能提供给其他的容器使用,也就是说怎么实现容器间的数据的共享呢?这就需要用到我们所提到 ...
随机推荐
- 详解Class加载过程
1.Class文件内容格式 2.一个class文件是被加载到内存的过程是怎样的? loading 把一个class文件装到内存里,class文件是一个二进制,一个个的字节 linking Verifi ...
- 常见的Mysql十款高可用方案
简介 我们在考虑MySQL数据库的高可用架构时,主要考虑如下几方面: 如果数据库发生了宕机或者意外中断等故障,能尽快恢复数据库的可用性,尽可能的减少停机时间,保证业务不会因为数据库的故障而中断. 用作 ...
- javascript里面的this指向问题
1:一般情况下this最终指向调用它的那个对象. 2:全局作用域或者普通函数中的this都会指向window. 例1:console.log(this); // 在控制台输出的是BOM顶级对象 wi ...
- Fullscreen API与DOM监听API
前言 以下几个API,在web开发中可以简化我们一部分交互操作. Fullscreen API 有时候我们想要全屏预览的效果,比如类似于图片预览.幻灯片播放等.全屏API是一个很好的选择. 基本用法 ...
- MeteoInfoLab脚本示例:添加南海脚图
添加南海脚图实际上就是增加一个地图坐标系(Axesm),在用axesm函数创建地图坐标系的时候可以指定position参数(即位置和大小),第1和第2个参数是坐标系的左下角x, y位置,后两个参数是坐 ...
- python实现elasticsearch操作-CRUD API
python操作elasticsearch常用API 目录 目录 python操作elasticsearch常用API1.基础2.常见增删改操作创建更新删除3.查询操作查询拓展类实现es的CRUD操作 ...
- C 和 C++ 打起来了!曾今最亲密的伙伴到现今的不爽?
70年代初,贝尔实验室创建了C语言,它是开发UNIX的副产品.很快C就成为了最受欢迎的编程语言之一.但是对于Bjarne Stroustrup来说,C的表达能力还不够.于是,他在1983年的博士论文中 ...
- 编程代码 | C++/C输出阳历万年历—精美日历制作
前言:本文章向大家介绍如何用C语言代码实现万年历使用实例.应用技巧.基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下. void输出万年历(int年, int月, int日 ...
- Linux关联文件扩展名和打开程序
手动为Linux关联文件扩展名与打开程序. 当Linux不认识某种扩展名的时候,需要为此扩展名创建一个MIME类型.Linux是依据MIME类型而不是扩展名来决定打开程序的. 再将此种MIME类型与某 ...
- Elasticsearch(5):添加文档
1 ES数据读写流程¶ ES中,每个索引都将被划分为若干分片,每个分片可以有多个副本.这些副本共同组成复制组,复制组中的分片在添加或删除文档时必须保持同步,否则,从一个副本中读取的数据将与从另一个 ...