开发者学堂课程【Docker 快速入门:Docker 镜像原理】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/850/detail/14039
Docker 镜像原理
内容介绍
一、docker 镜像是什么
二、docker 镜像的特点
一.docker 镜像是什么
1、镜像:
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
2、UnionFS(联合文件系统):
Union 文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
3、Docker 镜像加载原理:
docker 的镜像实际上由一层一层的文件系统组成,这种层级的文件系统 UnionFS。
bootfs(boot file system)主要包含 bootloader 和 kernel,//前面曾经反复强调过docker 真正工作的是 docker 背上的容器,那些容器每一个都是精简版的 Linux 系统,这个时候它主要引导加载 docker。这个图的意思是说这个 boot 文件系统实质上而言就是 Linux 内核,相当于这只蓝色大鲸鱼的背。
bootloader 主要是引导加载 kernel.Linux 刚启动时会加载 bootfs 文件系统,在Docker 镜像的最底层是 bootfs。这一层与我们典型的 Linux/Unix 系统是一样羊的,包含 boot 加载器和内核。当 boot 加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs 转交给内核,此时系统也。会卸载 bootfs。
rootfs (root file system),在 bootfs 之上。包含的就是典型 Linux 系统中的 /dev,/proc,/bin,/etc 等标准目录和文件。rootfs 就是各种不同的操作系统发行版,比如 Ubuntu,Centos 等等。
学过 Linux 的都知道,Ubuntu 和 centos 都是 Linux 这种概念下面一个具体的落地产品,和 kernel 内核相同,只不过定制的软件不一样。
平时我们安装进虚拟机的 CentOS 都是好几个 G,为什么 docker 这里才 200 M?
[root@atguigu docker]# docker images centos
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
centos latest 88ec626ba223 2 weeks ago 199.7 MB
[root@atguigu docker]#
对于一个精简的 OS,rootfs 可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用 Host 的 kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的 linux 发行版,bootfs 基本是一致的 rootfs 会有差别,因此不同的发行版可以公用 bootfs。
4、分层的镜像:
以我们的 pull 为例,在下载的过程中我们可以看到 docker 的镜像好像是在一层一层的在下载。
记得原来讲过一个东西,用最简单的:
[root@atquigu桌面]#docker pull hello-world
latest: Pulling from hello-world
b6d845cb453c:Pull complete
3535063d9957:Pull completeDigest:sha256:135a30bd414bd8d23e386763e36f3dc4ee8ed25d2d6068082c0af796513d9d0d
status: Downloaded newer image for hello-world:latest
[root@atquigu桌面]#docker images
root@atquiqu桌面]#
这个时候是一个镜像,但是根据所讲的一个镜像,它最终的干活的这个镜像。还是拿 hello word 来说,它对外暴露的是一个镜像ID,但是请看它下了几个,说明hello word 这个容器最终的这个镜像,模板也是由多层构成。
比如再写一个 centos:
Hello world 是两层:
b6d845cb453c:Pull complete
3535063d9957:Pull complete
Centos类似:
29466d114cd8: Alreadyexists
b298d692482d: Alreadyexists
88ec626ba223:Alreadvexists
下面就出现了一个问题, tomcat为什么这么大?
大家都知道,Tomcat 一般不会四百多 MB,下面画个图来解释一下:
最小的框里是 kernel,内核。
言下之意,这个内核怎么来的? bootfs 跑到这以后装 tomcat,把它装到 Linux 上面。
Java 的学习过程一定是先学 Java,再学 tomcat。Tomcat 要运行的时候,它就像是一个同心圆,花卷儿一样,这个是最底层。上面装的是 centos,再往外是 idk8,联合系统一层套一层,最外面是 tomcat 镜像。但这个 tomcat 镜像要全部用起来需要有内核,需要 centos,需要 idk8,最终才能变成 tomcat image,然后跑到这个大框这个集装箱里,就是 docker。
表面上看,tomcat 不大,但是为什么会达到400多 MB 呢?
[root@atguigu桌面]# docker ps
root@atguigu桌面]# docker images
到最后可以看到 tomcat 实际上是由多层文件构成,一层一层的打包,最终是 idk8加 centos 加 kernel,构成了一个精简版的基于 Linux 平台的一个 tomcat。这个时候把花卷跟这个比较起来,就能理解我们所说的联合文件系统的花卷了。
分层的这个镜像,可以看到它拉的时候,每一个前面都有个 ID,每一个都有这么一层,比方说像 mango 也拉了这么多。
下面运行一下:
也是很多层。这就是 docker 基于联合文件系统的分层原理,那为什么 docker 要采用这种分层结构呢?
5、为什么 docker 镜像要采用这种分层结构
最大的一个好处就是-共享资源
比如:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份 base 镜像,
同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
这里加载了这么多:
8475d7efa2f0:Pull complete
f7fdafe228d3: Pull complete
63474e4f2842:Pull complete
fa1aaced38d5:Pull complete
99dbeedc8084:Pull complete
33c59e00811a:Pull complete
84246776fc2a:Pull complete
beb16af23976:Pull complete
0c8b79a0b1ce:Pull complete
1e98967cc6c0:Pull complete
可以明显的感觉到第一次下载第一个镜像的时候非常慢,但是后续如果再重新下载会下载特别快,因为它会有一个缓存,它这个时候就是共享资源,所有的镜像都可以从全部的 base 下载而来。
二.Docker 镜像的特点
Docker 镜像都是只读的。
当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
Docker 镜像都是只读的,因为镜像不能去修改,最外层是读的 tomcat。
当容器启动的时候,一个新的可写层被加载到镜像底部,也就是要启动,要运行的就是最外层。比如拿一个鸡蛋,大家都知道鸡蛋是由三层构成,鸡蛋黄、鸡蛋白、鸡蛋壳。
正常情况下,是不可能隔着隔着蛋壳去操作里面。通常 tomcat 层被通常为容器层,容器层之下的都叫镜像,那么简单一句话就是吃花卷一定是先吃最外面这层,内部已经封装好了,最外层这个暴露的才是能看到的。






