博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深入理解 Docker 镜像 json 文件
阅读量:4072 次
发布时间:2019-05-25

本文共 3300 字,大约阅读时间需要 11 分钟。

很多时候,当大家谈论起Docker,经常会提到Docker作为容器解决方案,在虚拟化资源方面存在不小优势。轻量级虚拟化技术的优点暂且不谈,从软件生命周期来看,Docker在打包软件、分发软件方面的能力同样出众。而后者很大程度上依赖于Docker的镜像技术。

Docker镜像技术提供了一套标准,创造性地使用Dockerfile来规范化Docker化应用的制作流程,结果产生的Docker镜像便于传输与管理,最终通过Docker镜像运行Docker容器,完成容器化应用的交付。

经过本系列对于Docker镜像的镜像,大家应该已经清楚Docker镜像的存储、以及Docker镜像的内容。Docker镜像的内容,应该说包含两部分,除了镜像层中的文件之外,还包括一层镜像的json文件。镜像层文件的理解较为简单,但是Docker镜像的json文件理解起来就会稍显复杂。本文就带大家深入理解Docker镜像的json文件。

我们一直提到“通过Docker镜像运行Docker容器”,如果仔细思考这句话,可能依然会存在一些疑惑。不难的理解是:Docker镜像层中的文件全部属于静态的磁盘文件,而Docker容器属于一个动态的产物,可以认为是一个或者多个运行中的进程。那么,静态的Docker镜像转换为动态的Docker容器背后肯定会有一些不为人知的秘密。我们不妨带着以下几个问题来思考Docker镜像的json文件:

1.如何判定一个Docker镜像应该运行哪个进程,这部分信息存在哪?

2.有了以上信息,将Docker镜像运行成Docker容器的行为是谁在主导?

镜像的静态与容器的动态

这一次,我们依旧从动态静态这两个词来看Docker镜像的前世今生。首先,Docker镜像的镜像层文件属于静态文件,当容器运行起来之后这部分内容将作为Docker容器的文件系统内容,提供Docker容器的文件系统视角。我们带着这样的观点,再来看Dockerfile的概念。

在Dockerfile的原语中,大家肯定对ENV、VOLUME、EXPOSE以及CMD等命令非常熟悉。

ENV MYPATH=/root:ENV命令在构建Docker镜像时,为镜像添加一个环境变量,以便该环境变量在启动Docker容器时作用于容器内的进程;这部分信息不应该以静态文件的形式被打入Docker的镜像层文件。

VOLUME /data:VOLUME命令在构建Docker镜像时,为镜像添加一个数据卷标识,以便通过该镜像运行容器时为容器挂载一个数据卷;由于构建时真实的数据卷还不存在,所以这部分信息不应该以静态文件的形式被打入Docker的镜像层文件。

EXPOSE 80:EXPOSE命令在构建Docker镜像时,记录容器内部实际监听的端口,以便在通过bridge模式配置Docker容器网络时,将该端口与宿主机进行一次DNAT转换;这部分信息属于Docker容器运行时所需要的信息,也不应该以静态文件的形式被打入Docker的镜像层文件。

CMD ["./run.sh"]:CMD命令在构建Docker镜像时,记录启动Docker容器的执行命令入口,一般用以指定用户的应用程序;这部分配置信息更不应该以静态文件的形式被打入Docker的镜像层文件。

Dockerfile中以上举例的4类命令,通过分析,我们得出初步的结论:Dockerfile的部分命令各自包含一类动态信息,这类信息不属于Docker镜像层中的文件内容。

动态内容的存储

高移植性保障了Docker镜像的一次构建,多处运行,那么使得Docker容器可以顺利运行,Docker自然不会抛弃构建Docker镜像时的动态内容。因此,动态内容的存储就显得尤为重要。

此时就是Docker镜像json文件登场的时机。构建Docker镜像时,所有动态的信息都会会记录进相应Docker镜像的json文件中。需要注意的是,虽然镜像的动态信息会被存储于Docker镜像的json文件中,但是并不代表json文件中仅存储动态信息,Dockerfile构建过程中,机会所有的操作都会会记录在json文件中.

动态内容的执行

有了Docker镜像json文件来描述Docker容器的动态信息,那么json文件作为Docker镜像的一部分,在Docker体系中,由哪一模块来完成json文件中动态信息的解析与执行呢?

如果大家清楚“每一个Docker容器都是Docker Daemon的子进程”的话,肯定会联想到Docker Daemon。答案正是Docker Daemon。站在启动容器的角度上,Docker Daemon的作用就是以下两点:

1.将Docker镜像的镜像层文件作为Docker容器的rootfs。

2.提取Docker镜像json文件中的动态文件,确定启动进程,并为之配置动态运行环境。

Docker Daemon、Docker镜像以及Docker容器三者的简单示意图如下:

这里写图片描述

通过上图,我们可以使用ubuntu:14.04镜像运行Docker容器时,前者的镜像层layer内容将作为容器的rootfs;而前者的json文件,会由Docker Daemon解析,并提取出其中的容器执行入口CMD信息,以及容器进程的环境变量ENV信息,最终初始化容器进程。当然,容器进程的执行入口来源于镜像提供的rootfs。假如此时ubuntu 14.04镜像的json文件中又含有VOLUME信息,那么Docker Daemon将会为Docker容器在宿主机上创建一个文件目录,并挂载到容器内部,实现镜像中VOLUME动态信息的运用,其他动态信息的运用也大同小异。

Docker镜像json文件的真面目

全文分析至此,还是更多的从理论的角度阐述Docker镜像的json文件,那么现实情况中,此类json文件到底存的内容是什么呢?我们依然以ubuntu:14.04为例,揭开Docker镜像json文件的这面目。

image

一个含有标签的Docker镜像一般会有一个或者多个层级镜像组合而成,而每个镜像层都会含有一个json文件。上图中,我们展现了ubuntu:14.04镜像中4个镜像层的具体情况,特别分析了镜像8251da35e7a7e5855facec0b。通过查看这两个镜像的json文件,我们可以发现,两个json文件中的config属性中,除了理所应当不同的镜像ID之外,只有Cmd属性不同。由于镜像e5855facec0b是镜像8251da35e7a7的父镜像,同时构建子镜像的时候使用的Dockerfile命令为CMD ["/bin/bash"],因此子镜像在父镜像json文件的基础上,更新config属性中的Cmd属性,完成自身json文件的生成。Docker镜像中父子镜像的json文件有很大的相似性,子镜像仅在父镜像json文件的基础上,修改运行自身对应的Dockerfile命令后造成的差异。

镜像构建完毕,Docker镜像的镜像层layer文件以及json文件均准备完毕,那么当Docker Daemon通过此ubuntu:14.04镜像运行Docker容器时,首先提取最上层镜像的json文件,找到config属性中的Cmd命令,并在镜像层文件构成的容器rootfs中找到相应的执行程序,最终执行,完成容器的启动。(实际情况要更复杂,会涉及Entrypoint以及Cmd两部分的内容,本系列后续会深入深入两者的作用与区别)

当然,除了Cmd之外,json文件的config 属性中同时还存在User、ExposedPorts、Entrypoint、NetworkDisabled等一系列启动容器时所需的动态信息。

总结

Docker镜像的json文件扮演极其重要的角色,提供了静态镜像向动态容器的转化依据,同时清晰地记录了父子镜像之间的差异,基于此差异,后续Docker构建的cache机制才得以实现。

这里写图片描述

欢迎关注[Docker源码分析]微信公众号,更多精彩即将呈现。

你可能感兴趣的文章
PCA人脸识别过程
查看>>
再议PCA
查看>>
奇异值、奇异矩阵、SVD分解、正交矩阵
查看>>
向量的范数以及矩阵的范数
查看>>
Memo
查看>>
奇异值分解和特征值分解的一些备注
查看>>
PCA、最小平方差等中用拉格朗日求极值时对常见的一个f(x)=X'A'AX求导的证明
查看>>
PCA中的数据矩阵的一个备忘
查看>>
计算协方差矩阵的一个备忘
查看>>
Matlab使用PCA来做人脸识别的过程
查看>>
eclipse开发php全过程的搭建带debug的配置
查看>>
一种按照顺序提取向量中非0元素的方法
查看>>
DWZ中修改tree可以自定义节点的图标
查看>>
概率论与数理统计:随机变量、分布律,分布函数,密度函数
查看>>
统计学习方法备忘1
查看>>
X=XZ中Z有无穷解的解释
查看>>
Zend Studio7中的debug
查看>>
ZenFramework中的View对象初始化流程
查看>>
对偶空间
查看>>
稀疏表达唯一解的证明
查看>>