3.docker镜像探究

0x01. 镜像是什么

镜像是一种轻量级, 可执行的独立软件包, 用来打包软件运行环境和基于运行环境开发的软件, 它包含运行某个软件所需的所有内容, 包括代码, 运行时, 库, 环境变量和配置变量

所有的应用, 直接打包docker镜像, 就可以直接跑起来!

如何得到镜像呢?

  • 从远程仓库下载
  • 基友copy给你
  • 自己制作一个镜像 DockerFile

0x02. Docker镜像加载原理

UnionFS ( 联合文件系统 )

我们下载的时候看到的一层层就是这个

UnionFS ( 联合文件系统 ) : Union文件系统 ( UnionFS ) 是一种分层, 轻量级并且高性能的文件系统, 它支持对文件系统的修改作为一次提交来一层层的叠加, 同时可以将不同目录挂载到同一虚拟文件系统下, Union文件系统是Docker 镜像的基础 , 镜像可以通过分层来进行继承, 基于基础镜像 ( 没有父镜像 ) , 可以制作各种具体的应用镜像

特性 : 一次同时加载多个文件系统, 但从外面看起来, 只能看到一个文件系统, 联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

docker 镜像加载原理

docker的镜像实际上由一层一层的文件系统组成, 这种层级的文件系统就是UnionFS

bootfs( boot filesysytem ) 主要包含bootloader 和 kernel , bootloader 主要是引导加载kernel, linux刚启动时会加载bootfs文件系统,在docker镜像的最底层是bootfs。这一层与我们典型的linux、uninx系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs

rootfs ( root file system ) , 在bootfs之上, 包含的就是典型linux系统中的 /dev /proc /bin /etc 等标准目录和文件, rootfs就是各种不同的操作系统发行版, 比如 Ubuntu , Centos等等

image-20210406102147186

平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M ?

image-20210406103216652

对于一个精简的o0S , rootfs可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kerne,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别,因此不同的发行版可以公用bootfs。

0x03. 分层原理

分层的镜像

我们可以去下载一个镜像, 注意观察下载的日志输出, 可以看到是一层一层的在下载

image-20210406103525722

思考 : 为什么Docker镜像要采用这种分层的结构呢?

最大的好处, 我觉得莫过于是资源共享! 比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需要在磁盘上保留一份base镜像, 同时内存中也是需要加载一份base镜像, 这样就可以为所有的容器服务了,而且镜像的每一层都可以共享

查看镜像分层的方式可以通过 docker images inspect 命令

[root@centos7 ~]# docker image inspect redis:latest
[.....................
"GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/9bbbbb1513a947ef6798e2ceb33f324546e9c03c0aedaeec6ee94e7ceb6dd43b/diff:/var/lib/docker/overlay2/fca8b5e526ad25bf6e76417950c5bed8d1d71996f3d3246d8f5f66857cc38d2f/diff:/var/lib/docker/overlay2/abc6bcd9360dfd1cde300650cec2dbd98c726424f358565aca237ac67e84b742/diff:/var/lib/docker/overlay2/025bd1abda4e163c69ba5a991b8d0881f48e4f31598343f707a9bf3d0c5c2c56/diff:/var/lib/docker/overlay2/96fabbaf80522fbb4d4bb539ed414e51575c5e385465beb937078fbd61b401f3/diff",
                "MergedDir": "/var/lib/docker/overlay2/9b2059fa46a21c8230660fcbc522bbd14a148b6014ec0df6493b42908955be4c/merged",
                "UpperDir": "/var/lib/docker/overlay2/9b2059fa46a21c8230660fcbc522bbd14a148b6014ec0df6493b42908955be4c/diff",
                "WorkDir": "/var/lib/docker/overlay2/9b2059fa46a21c8230660fcbc522bbd14a148b6014ec0df6493b42908955be4c/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:346fddbbb0ff19bdb026afb053df490c0c73981a8a985882cf8ee3d716735e87",
                "sha256:a6ff16e8451ec08d277c59ee62169c65cca33293b62dddd3336365a1fe94d598",
                "sha256:9829ed4a48087cbe697bc56a7450bb3ab92a41b839d5b9250e410d02395439d9",
                "sha256:b0209f2252898cefd454e3c04a79b19058dbc652e1ded5b14be89df11e832167",
                "sha256:1fbf277d16836740a59ecaa122590826c4286267772b8af2f10ad1c36171881d",
                "sha256:7163f53b2285f2a583ca7a4e5fc788532e41ad093e3307f5767ebd131cce41a4"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

理解 :

所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于Ubuntu Linux 16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。

image-20210406104903212

在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。

image-20210406105207660

上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本。

image-20210406105427952

这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker在 Windows上仅支持windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW[1].下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。

image-20210406105544112

特点

docker镜像都是只读的, 当容器启动的时候, 一个新的可写层被加载到镜像的顶部!

这一层就是我们通常说的容器层, 容器之下的叫做镜像层 !

image-20210406110140920

如何提交一个自己的镜像 commit

0x04. commit镜像

docker commit   提交容器成为一个新的副本

# 命令和git原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[tag]

实战测试

# 1.启动一个默认的tomcat

# 2.发现这个默认的tomcat 是没有webapps应用, 镜像的原因, 官方默认镜像 webapps下面是没有文件的

# 3.我自己copy进去了基本的文件

# 4.将我们操作过的容器通过commit提交为一个镜像!我们以后就使用我们修改过的镜像即可
[root@centos7 ~]# docker commit -a="ymn" -m="add webapps app" d4d7a9e338fd tomcat02:1.0
sha256:b94af91084cb67f9e8f394ac024168d8a7b481c298acdabd0fcb07c48374ba87

# 这里还只是在本地,没有发布过去,等到了docker file再说

image-20210406112212784

学习方式说明︰理解概念,但是一定要实践,最后实践和理论相结合一次搞定这个知识

如果你想保存当前容器的状态, 就可以通过commit来提交获得一个镜像, 就好比我们学习虚拟机的时候拍摄快照到这里才算入门docker, 你觉得自己拼劲全力了, 可能只是别人的起点

docker的精髓在 容器数据卷 dockerfile docker网络 然后就是企业实战

原文地址:https://www.cnblogs.com/xcymn/p/15712427.html