Docker(四)进阶:Docker镜像概述和分层原理

简介: 镜像是一个只读模板,带有创建Docker容器的说明。通常,一个镜像基于另一个镜像,并带有一些额外的定制。例如,您可以构建一个基于ubuntu镜像的镜像,但是要安装Apache web服务器和您的应用程序,以及运行应用程序所需的配置细节。

前言


习本文需要一些了解Docker的概念以及一些名词。

个人网站:https://linzyblog.netlify.app/

一、Docker镜像概述


1、镜像是什么?


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


镜像是一个只读模板,带有创建Docker容器的说明。通常,一个镜像基于另一个镜像,并带有一些额外的定制。例如,您可以构建一个基于ubuntu镜像的镜像,但是要安装Apache web服务器和您的应用程序,以及运行应用程序所需的配置细节。


Docker 镜像(Image),就相当于是一个 模板,其中包含创建 Docker 容器的说明,可以通过模板来创建容器服务,通过这个镜像我们可以创建多个容器,最终服务运行或项目运行都是在容器中的。


2、如何获取镜像?


你可以创建自己的镜像,也可以只使用其他人创建并在Docker Hub中发布的镜像。要构建自己的镜像,需要创建一个Dockerfile,使用简单的语法定义创建和运行镜像所需的步骤。Dockerfile中的每一条指令都会在图像中创建一个层。当你更改Dockerfile并重新构建镜像时,只有那些已经更改的层才会重新构建。与其他虚拟化技术相比,这是镜像如此轻量级、小巧和快速的原因之一。


  • 从Docker Hub上拉取镜像(常用)
  • 自己制作镜像 Dockerfile 创建
  • 从别人那边拷贝一份


二、Docker镜像加载原理


1、UnionFs 联合文件系统


Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统被称为UnionFS。


  • Union文件系统(UnionFs)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,而且目录的物理位置是分开的。


  • Union文件系统可以把只读和可读写文件系统合并在一起,具有Copy-on-Write功能,允许只读文件系统的修改可以保存到可写文件系统当中。


  • Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。


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


2、Docker镜像加载原理


1)base镜像


base 镜像简单来说就是不依赖其他任何镜像,完全从0开始建起,其他镜像都是建立在他的之上,可以比喻为大楼的地基,docker镜像的鼻祖。


base 镜像的特性:

(1)不依赖其他镜像,从 scratch 构建。

(2)其他镜像可以之为基础进行扩展。


所以,能称作 base 镜像的通常都是各种 Linux 发行版的 Docker 镜像,比如 Ubuntu, Debian, CentOS 等。


我们以 CentOS 为例查看 base 镜像包含哪些内容。


d72dff06ca514a4099a40510c3234261.png


提问:docker cnetos的镜像大小200多M,和平时的所用的发行版的大小(几G)相差很大,为什么?


Linux 操作系统由内核空间和用户空间组成。


1.内核空间是 kernel,Linux 刚启动时会加载 bootfs 文件系统,之后 bootfs 会被卸载掉。

2.用户空间的文件系统是 rootfs,包含我们熟悉的 /dev, /proc, /bin 等目录。


81fedf681d524b6da6a188e0ee90d864.png


对于 base 镜像来说,底层直接用 Host 的 kernel,自己只需要提供 rootfs 就行了。


而对于一个精简的 OS,rootfs 可以很小,只需要包括最基本的命令、工具和程序库就可以了。相比其他 Linux 发行版,CentOS 的 rootfs 已经算臃肿的了,alpine 还不到 10MB。


由此可见对于不同的Linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。


我们平时安装的 CentOS 除了 rootfs 还会选装很多软件、服务、图形桌面等,需要好几个 GB 就不足为奇了。


base 镜像提供的是最小安装的 Linux 发行版。


2)bootfs


bootfs(boot file system):主要包含 bootloader 和 kernel。


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


3)rootfs


rootfs(root file system):在bootfs之上,包含类似于典型Linux系统中的/dev,/proc,/bin,/etc等标准目录文件。


  • rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等。


三、分层原理


参考文章:https://blog.51cto.com/wzlinux/2044797

Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。比如我们现在构建一个新的镜像,Dockerfile 如下:


# Version: 0.0.1
FROM debian               1.新镜像不再是从 scratch 开始,而是直接在 Debian base 镜像上构建。
MAINTAINER wzlinux
RUN apt-get update && apt-get install -y emacs        2.安装 emacs 编辑器。
RUN apt-get install -y apache2             3.安装 apache2。
CMD ["/bin/bash"]              4.容器启动时运行 bash。


构建过程:


bfdba7f71bbc4bb19e90afe5984afbbc.png


可以看到,Docker镜像都起始于一个基础镜像层,新镜像是从 Base 镜像一层一层叠加生成的。

当进行修改或增加新的内容时,就会在当前镜像层上,创建新的镜像层。


1、思考:为什么Docker镜像采用分层的结构呢?


1.分层最大的优点是共享资源。


2.多个镜像都可以基于相同的 Base 镜像构建而来,那么宿主机只需在磁盘上保存一份base 镜像即可。


3.同时内存中也只需要加载一份 Base 镜像,就可以为所有容器服务,而且镜像的每一层都可以被共享。


如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是否也会被修改?


答案是不会!


修改会被限制在单个容器内。


这就是我们接下来要说的容器 Copy-on-Write(COW) 特性。


1.新数据会直接存放在最上面的容器层。

2.修改现有数据会先从镜像层将数据复制到容器层,修改后的数据直接保存在容器层中,镜像层保持不变。

3.如果多个层中有命名相同的文件,用户只能看到最上面那层中的文件。


2、Copy-on-Write(COW)


Copy-on-write 是一种共享和复制文件以实现最大效率的策略。当我们试图读取一个文件时,Docker 会从上到下一层层去找这个文件,找到的第一个就是我们的文件,所以下面层相同的文件就被“覆盖”了。


而修改就是当我们找到这个文件时,将它“复制”到读写层并修改,这样读写层的文件就是我们修改后的文件,并且“覆盖”了镜像中的文件了。这最大限度地减少了 I/O 和每个后续层的大小。而删除就是创建了一个特殊的 whiteout 文件,这个 whiteout 文件覆盖的文件即表示删除了。


3、理解


这是一个三层的镜像分层结构图,在外部看整个镜像只有6个文件,app2.0 是 app1.0的更新版。


297cc777410c43248340b70776ac31ac.png


在这种情况下,上层镜像层中的文件会覆盖底层镜像层的文件。这样就使得文件的更新版本作为新镜像层添加到镜像中。


Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。



Linux 上可用存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。顾名思义,每种存储引擎都基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。


Docker 在 Windows 上仅支持 Windowsfilter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分层和COW。


07261c47098e4bacaaf50df326c26222.png


4、特点


Docker 镜像都是只读的,当你创建一个新的容器时,你会在基础层之上添加一个新的可写层,该层通常都称为 容器层


对正在运行的容器所做的所有更改,例如写入新文件、修改现有文件和删除文件,都被写入这个可写的容器层。


下图显示了基于ubuntu:15.04图像的容器。


dab5e6f0ebf5400b831779be3a8ccb4d.png


存储引擎处理有关这些层相互交互方式的详细信息。有不同的存储引擎可用,它们在不同的情况下各有优缺点。


四、Commit镜像


1、作用


将容器提交后,创建为一个新的镜像,命令与git原理类似。


2、格式:


 docker commit [OPTIONS] 容器id [目标镜像名[:TAG]]


3、可选项:


名称,简写 默认 描述
–author,-a 作者
–change,-c 将 Dockerfile 指令应用于创建的镜像
–message,-m 提交的描述消息
–pause,-p true 提交期间暂停容器


4、说明:


将容器的文件更改或设置后创建为新镜像。这允许您通过运行交互式shell调试容器,或者将工作数据集导出到另一个服务器。一般来说,最好使用Dockerfiles以文档化和可维护的方式来管理映像


提交操作将不包括容器内挂载的卷中包含的任何数据。


默认情况下,正在提交的容器及其进程将在映像提交时暂停。这减少了在创建提交过程中遇到数据损坏的可能性。如果不希望出现这种行为,请将 --pause 选项设置为false。


–change选项将对所创建的映像应用Dockerfile指令。

支持的Dockerfile指令:CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | ONBUILD | USER | VOLUME | WORKDIR


5、测试


1)提交一个容器


docker ps 找到一个新的容器,用commit命令提交一个容器,新增了一个命名为commit/test的镜像 tag为test1.0,用docker images查看本地镜像是否成功提交了。


90fa178cd6d8483dac20e6c227f61e37.png


2)提交一个新配置的容器


用docker inspect命令查看容器的环境变量


cec32f3eba0243868c164dd39596b990.png


提交一个新配置的容器,新增了一个命名为commit/test的镜像 tag为test2.0,跟上一个例子区分


7f64aff819974ae88e73cbac91e72fb8.png


3)实战测试


1.拉取并启动一个tomcat:9.0的镜像。


249960902551461faf6a3ef4d2d7866d.png


2.我们用docker exec命令进入tomcat 容器中,官方默认的tomcat镜像时没有 webapps 应用,需要将webapps.dist目录下的基本文件拷贝到webapps目录下。


ff819a0345c14aee81ea5203c1a1af2b.png


3.验证tomcat,访问http://localhost:8088/


2b6729fded99486ca7e6374a36d82cdc.png


4.将操作过后的tomcat容器提交为一个镜像,下次用的时候直接运行这个修改后的tomcat镜像即可。


c366bdee58bc44e7850ae022e8333945.png

目录
相关文章
|
13天前
|
缓存 Linux 网络安全
docker的镜像无法下载如何解决?
【10月更文挑战第31天】docker的镜像无法下载如何解决?
399 28
|
9天前
|
存储 关系型数据库 Linux
【赵渝强老师】什么是Docker的镜像
Docker镜像是一个只读模板,包含应用程序及其运行所需的依赖环境。镜像采用分层文件系统,每次修改都会以读写层形式添加到原只读模板上。内核bootfs用于加载Linux内核,根镜像相当于操作系统,上方为应用层。镜像在物理存储上是一系列文件的集合,默认存储路径为“/var/lib/docker”。
|
15天前
|
存储 监控 Linux
docker构建镜像详解!!!
本文回顾了Docker的基本命令和管理技巧,包括容器和镜像的增删改查操作,容器的生命周期管理,以及如何通过端口映射和数据卷实现容器与宿主机之间的网络通信和数据持久化。文章还详细介绍了如何使用Docker部署一个简单的Web应用,并通过数据卷映射实现配置文件和日志的管理。最后,文章总结了如何制作自定义镜像,包括Nginx、Python3和CentOS镜像,以及如何制作私有云盘镜像。
85 2
|
16天前
|
关系型数据库 MySQL Docker
docker环境下mysql镜像启动后权限更改问题的解决
在Docker环境下运行MySQL容器时,权限问题是一个常见的困扰。通过正确设置目录和文件的权限,可以确保MySQL容器顺利启动并正常运行。本文提供了多种解决方案,包括在主机上设置正确的权限、使用Dockerfile和Docker Compose进行配置、在容器启动后手动更改权限以及使用 `init`脚本自动更改权限。根据实际情况选择合适的方法,可以有效解决MySQL容器启动后的权限问题。希望本文对您在Docker环境下运行MySQL容器有所帮助。
29 1
|
9天前
|
缓存 JavaScript 安全
深入理解Docker镜像构建过程
深入理解Docker镜像构建过程
25 0
|
Ubuntu Linux 测试技术
Docker系列(1)--Docker原理及安装| 更文挑战
Docker系列(1)--Docker原理及安装| 更文挑战
105 0
|
存储 运维 Linux
2.docker架构,原理,安装及简单应用
docker的架构 先来看docker官网给出的docker架构图:
265 1
2.docker架构,原理,安装及简单应用
|
Ubuntu Linux 测试技术
Docker系列(1)--Docker原理及安装
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的。
126 0
Docker系列(1)--Docker原理及安装
|
Kubernetes Cloud Native 数据可视化
【云原生 | Docker篇】轻松学会原理|架构|安装|加速(一)(下)
【云原生 | Docker篇】轻松学会原理|架构|安装|加速(一)(下)
179 0
【云原生 | Docker篇】轻松学会原理|架构|安装|加速(一)(下)
|
存储 Kubernetes Cloud Native
【云原生 | Docker篇】轻松学会原理|架构|安装|加速(一)(上)
【云原生 | Docker篇】轻松学会原理|架构|安装|加速(一)(上)
130 0
【云原生 | Docker篇】轻松学会原理|架构|安装|加速(一)(上)