容器化之路:谁偷走了我的构建时间
副标题[/!--empirenews.page--]
随着全面云时代到来,很多公司都走上了容器化道路,老刘所在的公司也不例外。作为一家初创型的互联网公司,容器化的确带来了很多便捷,也降低了公司成本,不过老刘却有一个苦恼,以前每天和他一起下班的小王自从公司上云以后每天都比他早下班一个小时,大家手头上的活都差不多,讲道理不应该呀,经过多番试探、跟踪、调查,终于让老刘发现了秘密的所在。 作为一个开发,每天总少不了要出N个测试版本进行调试,容器化以后每次出版本都需要打成镜像,老刘发现每次他做一个镜像都要20分钟,而小王只要10分钟,对比来对比去只有这个东西不一样! Storage-Dirver到底是何方神圣?为什么能够导致构建时间上的差异?现在让我们来一窥究竟。 在回答这个问题之前我们需要先回答三个问题——什么是镜像?什么是镜像构建?什么是storage-driver? 什么是镜像? 说到镜像就绕不开容器,我们先看一张来自官方对镜像和容器解释的图片: 看完以后是不是更疑惑了,我们可以这样简单粗暴的去理解,镜像就是一堆只读层的堆叠。那只读层里到底是什么呢,另外一个简单粗暴的解释:里边就是放了一堆被改动的文件。这个解释在不同的storage-driver下不一定准确但是我们可以先这样简单去理解。 那不对呀,执行容器的时候明明是可以去修改删除容器里的文件的,都是只读的话怎么去修改呢?实际上我们运行容器的时候是在那一堆只读层的顶上再增加了一个读写层,所有的操作都是在这个读写层里进行的,当需要修改一个文件的时候我们会将需要修改的文件从底层拷贝到读写层再进行修改。那如果是删除呢,我们不是没有办法删除底层的文件么?没错,确实没有办法删除,但只需要在上层把这个文件隐藏起来,就可以达到删除的效果。按照官方说法,这就是Docker的写时复制策略。 为了加深大家对镜像层的理解我们来举个栗子,用下面的Dockerfile构建一个etcd镜像: 构建完成以后生成了如下的层文件: 每次进入容器的时候都感觉仿佛进入了一台虚机,里面包含linux的各个系统目录。那是不是有一层目录里包含了所有的linux系统目录呢? bingo答对!在最底层的层目录的确包含了linux的所有的系统目录文件。 上述Dockerfile中有这样一步操作
将外面目录的文件拷到了镜像中,那这一层镜像里究竟保存了什么呢? 打开发现里面就只有
到这里是不是有种管中窥豹的感觉,接下来我们再来了解什么是镜像构建,这样基本上能够窥其全貌了。 什么是镜像构建? 通过第一节的内容我们知道了镜像是由一堆层目录组成的,每个层目录里放着这一层修改的文件,镜像构建简单的说就是制作和生成镜像层的过程,那这一过程是如何实现的呢?以下图流程为例: Docker Daemon首先利用基础镜像ubuntu:14.04创建了一个容器环境,通过第一节的内容我们知道容器的最上层是一个读写层,在这一层我们是可以写入修改的,Docker Daemon首先执行了RUN apt-update get命令,执行完成以后,通过Docker的commit操作将这个读写层的内容保存成一个只读的镜像层文件。接下来再在这一层的基础上继续执行 ADD run.sh命令,执行完成后继续commit成一个镜像层文件,如此反复直到将所有的Dockerfile都命令都被提交后,镜像也就做好了。 这里我们就能解释为什么etcd的某个层目录里只有一个go目录了,因为构建的过程是逐层提交的,每一层里只会保存这一层操作所涉及改动的文件。 这样看来镜像构建就是一个反复按照Dockerfile启动容器执行命令并保存成只读文件的过程,那为什么速度会不一样呢?接下来就得说到storage-driver了。 什么是storage-driver? 再来回顾一下这张图: 之前我们已经知道了,镜像是由一个个的层目录叠加起来的,容器运行时只是在上面再增加一个读写层,同时还有写时复制策略保证在最顶层能够修改底层的文件内容,那这些原理是怎么实现的呢?就是靠storage-driver! 简单介绍三种常用的storage-driver: AUFS AUFS通过联合挂载的方式将多个层文件堆叠起来,形成一个统一的整体提供统一视图,当在读写层进行读写的时,先在本层查找文件是否存在,如果没有则一层一层的往下找。aufs的操作都是基于文件的,需要修改一个文件时无论大小都会将整个文件从只读层拷贝到读写层,因此如果需要修改的文件过大,会导致容器执行速度变慢,docker官方给出的建议是通过挂载的方式将大文件挂载进来而不是放在镜像层中。 OverlayFS (编辑:南平站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |