〖Docker指南③〗Docker镜像的深度解析

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 镜像是一种轻量级、可执行的独立软件包, 用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。

一、docker镜像



1.1 广度


一个完整的Docker镜像可以支撑一个Docker容器的运行,在 Docker容器运行过程中主要提供文件系统视角。


例如一个ubuntu的镜像,提供了一个基本的ubuntu的发行版,当然此镜像是不包含操作系统Linux内核的。

linux内核和ubuntu的Docker镜像的区别

传统虚拟机安装ubuntu会包含两部分,第一,某一个Linux内核的发行版本,比如Linux 3.8版本的内核;第二,第一个特定的Ubuntu发行版,这部分内容不包含Linux内核,但是包含Linux之外的软件管理方式,软件驱动,如 apt-get软件管理包等。

1.png



理解以上内容之后,就可以理解,为什么在一个Linux内核版本为3.8的ubuntu基础上,可以把Linux内核版本升级到3.18,而ubuntu的版本依然不变。


Linux内核+ubuntu操作系统发行版,组成一台工作的机器。

Docker很方便的利用了这一点,可以灵活替换ubuntu操作系统发行版,技术手段就是Docker镜像。


Docker的架构中,Docker镜像就是类似于“ubuntu操作系统发行版”,可以在任何满足要求的Linux内核之上运行。简单一点有“Debian操作系统发行版”Docker镜像、“Ubuntu操作系统发行版”Docker镜 像;如果在Debian镜像中安装MySQL 5.7,那我们可以将其命名为Mysql:5.7镜像;如果在Debian镜像中安装有Golang 1.3,那我们可以将其命名为golang:1.3镜像;以此类推,大家可以根据自己安装的软件,得到任何自己想要的镜像。


镜像的作用:回到Linux内核上来运行,通过镜像来运行时我们常常将提供的环境称为容器。


1.2 精度


刚才提到了“Debian镜像中安装MySQL 5.7,就成了mysql:5.7镜像”,其实在此时Docker镜像的层级概念就体现出来了。底层一个Debian操作系统镜像,上面叠加一个 mysql层,就完成了一个mysql镜像的构建。层级概念就不难理解,此时我们一般debian操作系统镜像称为mysql镜像层的父镜像。


层级管理的方式大大便捷了Docker镜像的分发与存储。说到分发,大家自然会联想到 Docker镜像的灵活性,传输的便捷性,以及高超的移植性。Docker Hub,作为全球的镜像仓库,作为Docker生态中的数据仓库,将全世界的Docker数据汇聚在一起,是Docker生态的命脉。


Docker有两方面的技术非常重要,第一是Linux 容器方面的技术,第二是Docker镜像的技术。从技术本身来讲,两者的可复制性很强,不存在绝对的技术难点,然而Docker Hub由于存在大量的数据的原因,导致Docker Hub的可复制性几乎不存在,这需要一个生态的营造。


二、docker镜像内容



初步接触Docker。相信很多爱好者都会和我一样,有这样一个认识:Docker 镜像代表一个容器的文件系统内容;


初步接触联合文件系统。联合文件系统的概念,让我意识到镜像层级管理的技术,每一层镜像都是容器文件系统内容的一部分。


镜像与容器的关系:

容器是一个动态的环境,每一层镜像中的文件属于静态内容,然而 Dockerfile 中的 ENV、VOLUME、CMD等内容最终都需要落实到容器的运行环境中,而这些内容均不可能直接坐落到每一层镜像所包含的文件系统内容中,那此时每一个Docker镜像还会包含json文件记录与容器之间的关系。


因此,Docker镜像的内容主要包含两个部分:第一,镜像层文件内容;第二,镜像json文件。


三、docker镜像存储



3.1 查看镜像层组成


我们可以通过命令 docker history issa/myubuntu:1.12 查看 issa/myubuntu:1.12,结果如下:

2.png



3.2 镜像层文件内容存储和镜像 json 文件存储


四、docker镜像的运行原理



当我们在我启动一个容器的时候,docker会加载这些只读层并在这些只读层的上面(栈顶)增加一个读写层。这时如果修改正在运行的容器中已有的文件,那么这个文件将会从只读层复制到读写层。该文件的只读版本还在,只是被上面读写层的该文件的副本隐藏。当删除docker,或者重新启动时,之前的更改将会消失。


当一个容器启动后,它将会被移到内存中,而引导文件系统则会被卸载,以留出更多的内存供initrd磁盘镜像使用。

3.png


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


Docker镜像的第二层是root文件系统rootfs,位于引导文件系统之上,rootfs可以是一种或多种操作系统如ubuntu文件系统。在bootfs之上 。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。


Docker镜像是由多个文件系统(只读层)叠加而成。当我们启动一个容器的时候,Docker会加载只读镜像层并在其上(即镜像栈顶部)添加一个读写层。如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏。当删除Docker容器,并通过该镜像重新启动时,之前的更改将会丢失。在Docker中,只读层及在顶部的读写层的组合被称为Union File System(联合文件系统)。


联合文件系统是一种轻量级的高性能分层文件系统,它支持将文件系统中的修改信息作为一次提交,并层层叠加,同时可以将不同目录挂载在同一个虚拟文件系统下,应用看到的是挂载的最终结果。


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


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


四、UnionFS(联合文件系统)



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


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


五、分层的镜像



以我们的pull为例,在下载的过程中我们可以看到docker的镜像好像是在一层一层的在下载 。


六、为什么 Docker 镜像要采用这种分层结构呢?



最大的一个好处就是 - 共享资源


比如:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像, 同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。


七、特点




Docker镜像都是只读的


当容器启动时,一个新的可写层被加载到镜像的顶部


这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”


八、Docker镜像commit操作



docker commit -m=“提交的描述信息” -a=“作者” 容器ID 要创建的目标镜像名:[标签名]

eg-1:


1.从Hub上下载ubuntu镜像到本地并成功运行docker run -it ubuntu

4.png


2.安装vim

apt-get -y install vim


3.vim test.txt

5.png


4.docker commit -m=“add vim” -a=“issavior” d50d5a500ed0 issa/myubuntu:1.12

6.png


eg-2:


  1. 从Hub上下载tomcat镜像到本地并成功运行docker run -it -p 8080:8080 tomcat
  2. 故意删除上一步镜像生产tomcat容器的文档
  3. 也即当前的tomcat运行实例是一个没有文档内容的容器,以它为模板commit一个没有doc的tomcat新镜像
  4. 启动我们的新镜像并和原来的对比


九、QA



1.问:为什么一个ubuntu:14.04镜像的镜像层的数量是4个,前三层的内容似乎有相同的,如etc?

这一点,细心的大家肯定发现了。首先,虽然三层都有,但是会存在两种情况,etc的子目录下有相同路径的文件,那么上层的会覆盖下层的文件;如果内部的文件路径不相同,那么都会存在,都会呈现给最上 层。[可别较真,说目录也是文件哈,意会]


2.问:关于docker安全性问题,对于安全是怎样处理的,如果我从hub下载镜像,能判别是否安全么?层级之间的依赖会导致一个崩了整个docker 都崩了么?

从流程上来讲,如果一切可控的话,我认为是安全的。但是依然会存在一些隐患,比如Dockerfile中基于的base images是否完全受信;镜像的传输过程是否受信;自己的private docker resgitry的安全级别达到什么样的层次,这些都有影响。


3.问:如何保证仅有的一个deamon的稳定性健壮性?

这个问题首先需要知道docker daemon的稳定性在哪些方面,那种场景下比较差?的确,docker daemon存在弊病。比如,daemon和容器的耦合等,目前general来讲,docker daemon保证绝对的稳定应该还做不到。


4.问:生产环境中怎么用docker备份mysql数据?

数据存储上docker,我目前的建议是:三思。举个简单的例子,官方的mysql镜像运行出来的 容器,密码是明文的,明文的密码存在于:docker inspect container_name, container.json文件中,容器的环境变量中,甚至在日志文件中都会存在,just think about it。当然也有办法解决,缓解这种情况。


5.问:如果是多层构建,中间的一个层做了升级或者bugfix,会潜在影响上层吧?

这个bugfix会在上层有体现,但是使用效果是不会有影响的,还有之前的bug会永远留在下层,但是没有影响。


相关文章
|
13天前
|
缓存 监控 持续交付
|
2天前
|
存储 监控 Linux
docker构建镜像详解!!!
本文回顾了Docker的基本命令和管理技巧,包括容器和镜像的增删改查操作,容器的生命周期管理,以及如何通过端口映射和数据卷实现容器与宿主机之间的网络通信和数据持久化。文章还详细介绍了如何使用Docker部署一个简单的Web应用,并通过数据卷映射实现配置文件和日志的管理。最后,文章总结了如何制作自定义镜像,包括Nginx、Python3和CentOS镜像,以及如何制作私有云盘镜像。
14 2
|
3天前
|
关系型数据库 MySQL Docker
docker环境下mysql镜像启动后权限更改问题的解决
在Docker环境下运行MySQL容器时,权限问题是一个常见的困扰。通过正确设置目录和文件的权限,可以确保MySQL容器顺利启动并正常运行。本文提供了多种解决方案,包括在主机上设置正确的权限、使用Dockerfile和Docker Compose进行配置、在容器启动后手动更改权限以及使用 `init`脚本自动更改权限。根据实际情况选择合适的方法,可以有效解决MySQL容器启动后的权限问题。希望本文对您在Docker环境下运行MySQL容器有所帮助。
9 1
|
4天前
|
存储 Java 开发者
成功优化!Java 基础 Docker 镜像从 674MB 缩减到 58MB 的经验分享
本文分享了如何通过 jlink 和 jdeps 工具将 Java 基础 Docker 镜像从 674MB 优化至 58MB 的经验。首先介绍了选择合适的基础镜像的重要性,然后详细讲解了使用 jlink 构建自定义 JRE 镜像的方法,并通过 jdeps 自动化模块依赖分析,最终实现了镜像的大幅缩减。此外,文章还提供了实用的 .dockerignore 文件技巧和选择安全、兼容的基础镜像的建议,帮助开发者提升镜像优化的效果。
|
9天前
|
存储 缓存 Java
Java应用瘦身记:Docker镜像从674MB优化至58MB的实践指南
【10月更文挑战第22天】 在容器化时代,Docker镜像的大小直接影响到应用的部署速度和运行效率。一个轻量级的Docker镜像可以减少存储成本、加快启动时间,并提高资源利用率。本文将分享如何将一个Java基础Docker镜像从674MB缩减到58MB的实践经验。
21 1
|
16天前
|
Docker 容器
docker:记录如何在x86架构上构造和使用arm架构的镜像
为了实现国产化适配,需将原x86平台上的Docker镜像转换为适用于ARM平台的镜像。本文介绍了如何配置Docker buildx环境,包括检查Docker版本、安装buildx插件、启用实验性功能及构建多平台镜像的具体步骤。通过这些操作,可以在x86平台上成功构建并运行ARM64镜像,实现跨平台的应用部署。
123 2
|
17天前
|
存储 应用服务中间件 云计算
深入解析:云计算中的容器化技术——Docker实战指南
【10月更文挑战第14天】深入解析:云计算中的容器化技术——Docker实战指南
43 1
|
20天前
|
网络协议 Docker 容器
docker pull命令拉取镜像失败的解决方案
docker pull命令拉取镜像失败的解决方案
429 0
|
24天前
|
缓存 网络协议 网络安全
docker中DNS解析问题
【10月更文挑战第6天】
89 6
|
20天前
|
Go Docker Python
docker的python与go镜像的制作
docker的python与go镜像的制作
21 1