32利用文件系统保存数据_网易技术实践|Docker文件系统实战

e1560342248a5cb10acb6d2c33a6e1e1.png

在本文中,我们来实战构建一个Docker镜像,然后实例化容器,在Docker的生命周期中详细分析一下Docker的文件存储情况和DockerFile优化策略。

82b89fd613069efdb46190c32ffe0cf9.png

b2dbbd0aa12b2e8cf0f62d85d2acfe63.png

在开始实战之前,我们先介绍一个概念,联合文件系统(Union File System)。联合文件系统是实现Docker镜像的技术基础,支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。镜像的分层存储和继承就是基于此特性实现。

下面是Docker官方的一张描述文件系统的图片,显示了一张联合文件系统在串联镜像层和容器层起到的作用

3780b33d8f36c172fe5b2be4d37de449.png

Docker支持多种联合文件系统,常见的有aufs,deviceMapper,overlay,overlay2,本文章中使用的系统版本为debian9.1,Docker版本为17.06.2-ce,默认使用是overlay2。

看到这里如果你已经对Docker文件系统有了简单的概念,那么让我们开始实战,来对分层文件系统的存储方式进行更加深入的了解。

镜像层

这是一个云信私有化项目中基于debian系统镜像创建的jdk8基础镜像,为了方便阅读和分析,我们Dockerfile进行了一些精简,只保留核心部分内容

FROM hub.c.163.com/library/debian:stretch
MAINTAINER nim
#下载jdk
ADD http://10.173.11.100/nim/jdk-8u202-linux-x64.tar.gz /usr/local/nim/
#解压jdk并删除
RUN tar -xzvf /usr/local/nim/jdk-8u202-linux-x64.tar.gz -C /usr/local/nim/ 
&& rm /usr/local/nim/jdk-8u202-linux-x64.tar.gz
#设置环境变量
ENV JAVA_HOME=/usr/local/nim/jdk1.8.0_202
ENV PATH=$JAVA_HOME/bin:$PATH
CMD ["/bin/bash"]

根据构建镜像,查看构建结果,原基础镜像100M,构建后镜像体积697M。

a67eea6b5c471fd82a11eee06707a2f8.png

镜像存储

现在开始看一下构建镜像工作在文件层存储情况。首先我们使用Docker history查看一下刚刚构建镜像情况,可以看到基础镜像占用100M,两个镜像分层占用194MB和403M。

1344b611c7998c78d4af3a0770dde3f4.png

接下来我们看查看一下文件系统中的存储情况,本环境使用overlay2,Docker镜像层存储默认路径为/var/lib/Docker/overlay2/,可以看到镜像存储目录下有4个目录,其中110M的对应是基础镜像,另外两个为ADD JDK(186M)和解压JDK压缩包的镜像分层(389M)。

e6c2782eb920a4f09f75dcfe91a76842.png

其中的l目录包含了所有层的软连接,软链接使用短名称,避免mount时候参数达到页面大小限制。

178b6b3f26103353f199690139b985be.png

下面我们了解一下,每个分层中的文件内容。基础镜像分层包含diff文件夹和link文件,diff文件夹中存放当前分层内容,link文件记录短名称。

a1ba4070e14bf227d2b844d7e2cf5472.png

接下来看一下COPY JDK生成的内容,diff文件夹保存了jdk压缩包,本层相比基础镜像层,多了lower,merged,work三个文件/文件夹,其中lower记录了此层的下层ID(基础镜像层),merged目录作为提供了统一视图,在容器层读写层被使用,work目录用于联合挂载指定的工作目录,使用过程对用户不可见。

3528f897319a4074b67ed14b7d444c84.png

解压JDK层的文件夹结构内容和上一层类似,主要关注jdk压缩包占用空间为0,表示已被删除。

19ef1e632120694e7b14d7541f73bf73.png

现在来重点关注一个问题,镜像大小等于所有分层相加,在后续分层中被删除的jdk压缩包仍然要占用存储空间,这并不是我们原本意图,因此这里就出现了镜像文件进行优化的点。优化后的Dockerfile如下

FROM hub.c.163.com/library/debian:stretch
MAINTAINER nim
RUN curl -o /usr/local/nim/jdk-8u202-linux-x64.tar.gz http://10.173.11.100/nim/jdk-8u202-linux-x64.tar.gz 
&& tar -xzvf /usr/local/nim/jdk-8u202-linux-x64.tar.gz -C /usr/local/nim/ 
&& rm /usr/local/nim/jdk-8u202-linux-x64.tar.gz 
&& export JAVA_HOME=/usr/local/nim/jdk1.8.0_202 
&& export PATH=$JAVA_HOME/bin:$PATH
CMD ["/bin/bash"]

借这个优化后的内容,我们再谈一下构建Docker镜像时在时间和空间可优化的点

  1. 组合运行语句:合并相同类型构建语句,可以有效减少镜像分层;
  2. 利用镜像构建缓存:时间同步,基础软件安装等固定内容在镜像前部分处理,镜像重新构建时会使用缓存,节省时间;
  3. 清理中间产物:注意安装过程中使用的软件和压缩包在一定要同一层里清理,否则仍然会占用镜像空间;
  4. 构建语句优化:比如ADD在处理本地文件时可以直接解压缩,起到COPY + RUN tar的作用;
  5. 优化基础镜像源:国内高校和大型IT企业都有创建镜像站,选择一个稳定更新及时的镜像站可以有效缩短构建时间;

举例的镜像中优化策略涉及1,3条,用curl替代add,与解压和删除合并为一层,Dockerfile减少了层数,清理中间过程的jdk安装包,下图是优化后镜像体积变化:

5d0210c764a614640d4c3630ac2eb2e9.png

构建镜像真的是层数越少越好吗?当然不是这么绝对,尤其在早期镜像版本不是很稳定或是后续迭代比较频繁时,合理的镜像分层会减少编译时间,降低出错概率,也可以让Dockerfile更具有可读性。可以再稳定版本形成之后对镜像进行二次优化。

镜像元数据

分析一个镜像元数据我们主要关注三个目录

/var/lib/Docker/image/overlay2/imaged/
/var/lib/Docker/image/overlay2/layerdb/
/var/lib/Docker/overlay2/

第一个目录保存镜像基础元数据,第二个目录保存镜像分层元数据,第三个是上文提到的分层存储目录,保存实际分层内容。下面就根据实际情况来看一下,元数据与存储信息是如何关联起来的。

Docker镜像的基本信息保存在/var/lib/Docker/image/overlay2/imaged/content/sha256/下面,可以根据Docker image ID在此目录下查找到对应ID开头文件。此文件中以json的形式保存了该镜像的分层文件系统、构建信息、相关容器等内容。

bf9003f5224ea6ee12dcf8b08711e4ce.png

第二个目录/var/lib/Docker/image/overlay2/layerdb/sha256/保存分层元数据,每一个分层元数据目录下有cache-id,diff,size信息,其中cache-id对应分层存储层,diff关联镜像基础元数据信息。

cb123147128bbe329dcec29618eec801.png

50db45a839e48c465a359ed83f34a04c.png

ea9d983514d57bed258fe7e4847fb0b2.png

容器层

首先我们来启动一个容器,挂载宿主机/opt/yunxin目录到容器/usr/local/yunxin目录

573d7597e52a7fe7b5d67b8aa616469f.png

创建容器完成之后,在镜像存储目录/var/lib/Docker/overlay2/会生成容器的初始层和读写层,两者使用相同标识,初始层后面多了-init。初始层中主要保存初始化容器环境时,与容器相关的环境信息,如容器主机名,主机host信息以及域名服务文件等;读写层用于容器的读写,Docker容器内的进程只对读写层拥有写权限,而对其他层文件内容只拥有读权限

12d5e8f0ae51f185feaa94a3c3a34c21.png

接下来我们进入容器操作进行一系列操作,再根据结果分析一下读写层对于文件的保存和处理,下面是操作和对应结果以及读写层实际文件存储情况。

0b6a109a4d9c43b6000c031196b49885.png

b43adeb8781f8f89284608304d99e124.png

读写层中的merged文件夹提供了统一视图,面向用户展示联合文件系统挂载完成的最终形态。

6d4e3d01b02ab77c0942262b24fe4bce.png

接下来我们再基于同一个镜像启动几个容器实例,然后来查询一下Docker容器使用空间,只有第一个容器由于上面修改文件只占用154k,新启动的容器并没有额外占用空间。可见基于同一个镜像创建容器时,所有的容器共享镜像层内容,有效节约了空间。读写层只保存修改内容,如果是操作镜像层文件,Docker采用的是修改时复制策略(copy-on-write)。这时回头再看一下第一节出现的两张图,会对Docker的文件系统有了更深的体会。

98402fc445e223bcb3d604a0f04f8616.png

结语

Docker 镜像和容器文件系统相关知识在云信私有化产品的镜像管理和运维存储管理方面作出理论支撑,但这只是深入了解Docker的开始。随着时间的积淀和云信旗下IM、音视频、点播以及众多相关产品私有化工作的深入,更多的模块和镜像,更多的客户和需求,更复杂的网络和环境都逐渐呈现在我们面前。Docker作为构建云信私有化服务的基础,只有更深入的去了解原理才能在使用中去更好的优化产品和开展运维。希望我们能为用户提供更可靠的云信私有化服务,也希望能在后续的文章中能与大家分享更多关于Docker的知识。

立即了解网易云信私有云>>

更多技术干货,欢迎关注vx公众号“网易智慧企业技术+”。系列课程提前看,精品礼物免费得,还可直接对话CTO。

82b89fd613069efdb46190c32ffe0cf9.png

听网易CTO讲述前沿观察,看最有价值技术干货,学网易最新实践经验。网易智慧企业技术+,陪你从思考者成长为技术专家。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/558327.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

POI读取word文件,(支持HSSF和XSSF两种方式)

POI读取word文件&#xff0c;&#xff08;支持HSSF和XSSF两种方式&#xff09; 参考&#xff1a;HSSF&#xff0c;XSSF&#xff0c;SXSSF三种方式 1.引用maven&#xff08;版本必须一致&#xff09; <dependency><groupId>org.apache.poi</groupId><art…

pythonsqlite事务_python sqlite3 的事务控制

Python sqlite3 的事务控制官方文档的描述&#xff1a;Controlling TransactionsBy default, the sqlite3 module opens transactions implicitly before a Data Modification Language (DML) statement (i.e. INSERT/UPDATE/DELETE/REPLACE), and commits transactions implic…

二叉树遍历的超简单方法(详细、简单)

二叉树遍历的超简单方法 参考链接&#xff1a;https://wenku.baidu.com/view/e5463e4203d8ce2f0166230a.html 已修改部分问题。 三种常见二叉树的遍历&#xff1a; 先序遍历的递归算法定义&#xff08;简称根左右&#xff09; 若二叉树非空&#xff0c;则依次执行如下操作&a…

怎么看我装的sql能不能用_深入浅出sql优化(三)之单表索引优化

大家好&#xff0c;我是闲水&#xff0c;每天更新java最新最热技术&#xff0c;对java感兴趣的朋友记得关注一下哦。注意 &#xff1a;这是SQL性能优化第三章&#xff0c;点击关注查看前置内容。上篇文章我们主要了解了索引优化的标尺"Explain"怎么用&#xff0c;这一…

java类加载顺序(spring容器下)

执行顺序&#xff1a;父类静态块–>子类静态块–>父类非静态块–>父类构造方法–>子类非静态块–>子类构造方法–>自动装载的方法 子类和父类均加上Service注解&#xff0c;将其交给spring容器管理。 父类&#xff1a; Service public class Father {publ…

python 绘图 hist bin参数_Python-hist,distplot bin宽度不一致问题的解决方案

python的hist有一个bug&#xff0c;之前一直没有解决。绘制直方图的时候&#xff0c;往往出现两组数据由于分布不一样&#xff0c;&#xff0c;导致出来的图片中&#xff0c;虽然是一样数目的bins&#xff0c;但是bin的宽窄不同。而我想得到的是&#xff0c;&#xff0c;虽然数…

Nginx反向代理的使用

1. 常用服务器比较 apache: 功能完善&#xff0c;历史悠久&#xff0c;模块支持非常丰富&#xff0c;属于重量级产品&#xff0c;比较耗费内存。缺点:处理每一个php比较费资源&#xff0c;导致如果高并发时会耗费服务器资源无法处理更多请求。 lighttpd: 内存开销低&#xff0…

python继承语法_python中继承父类的例子(python3的语法)

#codingutf8class Cup:#构造函数&#xff0c;初始化属性值def __init__(self,capacity,color):self.capacitycapacityself.colorcolordef retain_water(self):print("杯子颜色&#xff1a;"self.color"&#xff0c;杯子容量&#xff1a;"self.capacity&quo…

Rabbit发送消息,消费者消费异常

Rabbit发送消息&#xff0c;消费者消费异常 背景&#xff1a; 在步骤1下创建订单&#xff0c;步骤2下提交消息 Transactionalpublic void tradeHandler(Map map) { // 1.生成统一订单 var unifyOrder orderService.create(orderService.getUnifyOrderDTO(fee, alipayOrder));…

jwt token 太长_理解 JWT 鉴权的应用场景及使用建议

JWT 介绍JSON Web Token(JWT)是一个开放式标准(RFC 7519)&#xff0c;它定义了一种紧凑(Compact)且自包含(Self-contained)的方式&#xff0c;用于在各方之间以JSON对象安全传输信息。这些信息可以通过数字签名进行验证和信任。可以使用秘密(使用HMAC算法)或使用RSA的公钥/私钥…

如何使用explain进行SQL语句调优

参考&#xff1a;https://mp.weixin.qq.com/s/kYcrHtE82-sOqNOp_qM4Ig

microsoft vbscript编译器错误怎么解决_win7系统ie应用程序错误怎么办 ie应用程序错误解决方法【详解】...

windows系统自带的ie浏览器很少用户会去使用到&#xff0c;它运行起来比其他的浏览器要慢很多&#xff0c;而且经常会出现各种各样的问题&#xff0c;最近有位win7系统用户&#xff0c;在使用ie浏览器的时候&#xff0c;发生了应用程序错误的情况&#xff0c;那么win7系统ie应用…

简述python爬虫_python爬虫入门篇了解

1. 爬虫分类&#xff1a;1.1 通用爬虫&#xff1a;例如搜索引擎&#xff1a;无差别的收集数据&#xff1b;提取存储关键字&#xff1b;构建索引库&#xff1b;给用户提供搜索接口。1.2 聚焦爬虫&#xff1a;有针对性的编写特定领域数据的爬取程序。2. Robots协议&#xff1a;指…

修改固态硬盘的物理序列号_买固态怕踩坑?收下这些软件,轻松鉴别好坏

再有半个月&#xff0c;就迎接年中的促销旺季。不少朋友都希望趁着各种优惠、跳楼价&#xff0c;组一台梦想机、升级一下自己的电脑。说到体验升级&#xff0c;相信就算是DIY新手和硬件小白都知道&#xff0c;要想电脑快&#xff0c;必须选固态。但是固态参数多&#xff0c;又是…

python乘法表代码注释_Python统计python文件中代码,注释及空白对应的行数示例【测试可用】...

本文实例讲述了Python实现统计python文件中代码,注释及空白对应的行数。分享给大家供大家参考&#xff0c;具体如下&#xff1a;其实代码和空白行很好统计&#xff0c;难点是注释行python中的注释分为以#开头的单行注释或者以开头以结尾 或以"""开头以"&qu…

32位python和64位python区别_python32位和64位有什么区别

python32位和64位有什么区别&#xff1f;64位能够用更大的内存空间&#xff0c;64位可以在64位的系统下运行&#xff0c;但是不能在32位系统下运行。32位能够在32位和64位上运行&#xff0c;考虑到兼容性&#xff0c;建议使用32位的python。如何查看python是32位还是64位可使用…

《常用控制电路》学习笔记——数控锁相环调速电路

序言 今天开始我将把自己学习《常用控制电路》的一些内容发到互联网上&#xff0c;希望能和大家交流学习。 这本书主要介绍了一系列控制电路的经典案例&#xff0c;进行了电路和代码的设计&#xff0c;我将把这本书中学习到的内容和学习的过程尽量准确的分享出来与大家交流&…

《常用控制电路》学习笔记——数字控制直流电动机调速电路

书中该节讲述的电路通过ADC芯片将电位器的阻值转换为电压量&#xff0c;然后使用单片机输出PWM进行电路控制。本电路也可扩展应用至需要模拟量输入与输出的场合。 目录 一、系统设计思路 二、各模块电路分析 2.1电路构成 2.2工作状态分析 三、程序分析 3.1 变量定义 3.…

《常用控制电路》学习笔记——数控直流恒流源电路

书中该项目内容设计了一个从交流220V市电作为供电电源的恒流源电路&#xff0c;并且此电路可由加减计数器74LS193控制输出的电流大小。 目录 一、系统方案 二、各模块电路分析 整流滤波及稳压电路 数字量控制电路 数模转换电路 数控恒流源产生电路 三、电路仿真结果 四…

图像太宽无法输出请裁剪图像或降低分辨率然后重试_真·无监督!延世大学提出图像到图像无监督模型,实验结果超SOTA...

作者 | 蒋宝尚编辑 | 丛 末图像翻译目的是用模型将源域图像转换到目标域图像&#xff0c;通常涉及标签图到场景图的转换、图像风格、人脸的属性变换、标签图到场景图的转换。图像翻译任务自生成对抗网络提出就得到了快速发展&#xff0c;例如经典的pix2pix、CycleGAN、StarGAN。…