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容器运行的时候,会产生一系列的文件,那么我们希望容器产生的数据能提供给其他的容器使用,也就是说怎么实现容器间的数据的共享呢?这就需要用到我们所提到 ...
随机推荐
- Linux网卡命名规则
网卡命名 一.为什么需要这个 服务器通常有多块网卡,有板载集成的,同时也有插在PCIe插槽的.Linux系统的命名原来是eth0,eth1这样的形式,但是这个编号往往不一定准确对应网卡接口的 ...
- Python基础笔记1-Python读写yaml文件(使用PyYAML库)
最近在搭建自动化测试项目过程中经常遇到yaml文件的读写,为了方便后续使用,决定记下笔记. 一,YAML 简介 YAML,Yet Another Markup Language的简写,通常用来编写项目 ...
- package.json文件配置说明
1.什么是package.json package.json文件是Node.js项目中的一个描述文件,执行npm init命令初始化项目后,在项目的根目录下自动生成该文件.package.json包含 ...
- docker 和 k8s 调研总结
一. docker简介 环境配置 软件开发最大的麻烦事之一,就是环境配置.用户计算机的环境都不相同,你怎么知道自家的软件,能在那些机器跑起来? 用户必须保证两件事:操作系统的设置,各种库和组件的安装. ...
- 每个人都可以用C语言写的推箱子小游戏!今天你就可以写出属于自己项目~
C语言,作为大多数人的第一门编程语言,重要性不言而喻,很多编程习惯,逻辑方式在此时就已经形成了.这个是我在大一学习 C语言 后写的推箱子小游戏,自己的逻辑能力得到了提升,在这里同大家分享这个推箱子小游 ...
- 【思维】UVA 11300 Spreading the Wealth
题目大意 vjudge链接 有n个人围圆桌而坐,每个人有Ai个金币,每个人可以给左右相邻的人一些金币. 若使得最终所有人金币数相等,求最小金币转移数. 数据范围 n<1000001 样例输入 3 ...
- spring boot:用redis+lua限制短信验证码的发送频率(spring boot 2.3.2)
一,为什么要限制短信验证码的发送频率? 1,短信验证码每条短信都有成本制约, 肯定不能被刷接口的乱发 而且接口被刷会影响到用户的体验, 影响服务端的正常访问, 所以既使有图形验证码等的保护, 我们仍然 ...
- linux(centos8):阿里云ecs配置smtps发邮件(解决不能通过25端口发邮件问题)
一,2016年9月后购买的阿里云ecs不再支持通过25端口发送邮件 官方的建议是使用465端口 465端口(SMTPS): 465端口是为SMTPS(SMTP-over-SSL)协议服务开放的 它是S ...
- 笔趣阁小说 selenium爬取
import re from time import sleep from lxml import etree from selenium import webdriver options = web ...
- JavaSE学习笔记03流程控制
Java流程控制 1.顺序结构 java的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句往下执行. 顺序结构是最简单的算法结构,它是任何一个算法都离不开的一种基本算法结构. 2. 选择结构 ...