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

目录
相关文章
|
24天前
|
Docker 容器
将本地的应用程序打包成Docker镜像
将本地的应用程序打包成Docker镜像
|
8天前
|
NoSQL PHP MongoDB
docker push推送自己搭建的镜像
本文详细介绍了如何搭建和复盘两个Web安全挑战环境:人力资源管理系统和邮件管理系统。首先,通过Docker搭建MongoDB和PHP环境,模拟人力资源管理系统的漏洞,包括nosql注入和文件写入等。接着,复盘了如何利用这些漏洞获取flag。邮件管理系统部分,通过目录遍历、文件恢复和字符串比较等技术,逐步绕过验证并最终获取flag。文章提供了详细的步骤和代码示例,适合安全研究人员学习和实践。
33 3
docker push推送自己搭建的镜像
|
25天前
|
数据库 Docker 容器
Docker在现代软件开发中扮演着重要角色,通过Dockerfile自动化构建Docker镜像,实现高效、可重复的构建过程。
Docker在现代软件开发中扮演着重要角色,通过Dockerfile自动化构建Docker镜像,实现高效、可重复的构建过程。Dockerfile定义了构建镜像所需的所有指令,包括基础镜像选择、软件安装、文件复制等,极大提高了开发和部署的灵活性与一致性。掌握Dockerfile的编写,对于提升软件开发效率和环境管理具有重要意义。
48 9
|
25天前
|
存储 缓存 运维
Docker镜像采用分层存储,每层代表镜像的一部分,如基础组件或应用依赖,多层叠加构成完整镜像
Docker镜像采用分层存储,每层代表镜像的一部分,如基础组件或应用依赖,多层叠加构成完整镜像。此机制减少存储占用,提高构建和传输效率。Docker还通过缓存机制提升构建和运行效率,减少重复工作。文章深入解析了Docker镜像分层存储与缓存机制,包括具体实现、管理优化及实际应用案例,帮助读者全面理解其优势与挑战。
43 4
|
16天前
|
监控 NoSQL 时序数据库
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
153 77
|
24天前
|
监控 Docker 容器
在Docker容器中运行打包好的应用程序
在Docker容器中运行打包好的应用程序
|
3天前
|
Unix Linux Docker
CentOS停更沉寂,RHEL巨变限制源代:Docker容器化技术的兴起助力操作系统新格局
操作系统是计算机系统的核心软件,管理和控制硬件与软件资源,为用户和应用程序提供高效、安全的运行环境。Linux作为开源、跨平台的操作系统,具有高度可定制性、稳定性和安全性,广泛应用于服务器、云计算、物联网等领域。其发展得益于庞大的社区支持,多种发行版如Ubuntu、Debian、Fedora等满足不同需求。
15 4
|
18天前
|
数据建模 应用服务中间件 nginx
docker替换宿主与容器的映射端口和文件路径
通过正确配置 Docker 的端口和文件路径映射,可以有效地管理容器化应用程序,确保其高效运行和数据持久性。在生产环境中,动态替换映射配置有助于灵活应对各种需求变化。以上方法和步骤提供了一种可靠且易于操作的方案,帮助您轻松管理 Docker 容器的端口和路径映射。
59 3
|
25天前
|
存储 缓存 监控
Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
本文介绍了Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
63 7