锡林郭勒盟建设工程管理网站,wordpress首页刷新,创意做网站公司,吉化北建公司官网戳蓝字“CSDN云计算”关注我们哦#xff01;技术头条#xff1a;干货、简洁、多维全面。更多云计算精华知识尽在眼前#xff0c;get要点、solve难题#xff0c;统统不在话下#xff01;作为云计算的当红明星Docker 来势汹汹,它就像一场森林大火#xff0c;烧到了我们中间… 戳蓝字“CSDN云计算”关注我们哦技术头条干货、简洁、多维全面。更多云计算精华知识尽在眼前get要点、solve难题统统不在话下作为云计算的当红明星Docker 来势汹汹,它就像一场森林大火烧到了我们中间。因为工作的原因每天都会和容器云打交道。但是我发现经常会有些新加入的同事在理解Docker命令方面存在一些问题尤其是在Docker 镜像底层的工作原理和容器与容器镜像的关系上。通常情况下一项新的技术诞生时往往会伴随着较多的媒体宣传甚至炒作且在推广产品的过程中往往会出现一些新的技术名词让人感觉云里雾里。Docker 的诞生和推广正是在这种情况下进行的。对于产品本身而言媒体的宣传和炒作可以帮助他们快速的在市场中进行推广但是这种宣传和炒作也会导致很多用户很难看清被宣传产品的技术的本质不利于用户对技术的掌握更加不利于用户对产品的深度使用。 一般情况下只有真正理解了某门技术的原理才能真正掌握这一门技术接下来才能去深入的使用这门技术。下面我们会由浅入深出的带大家了解下Docker 镜像及其相关技术的原理和本质。 容器 VS 容器镜像 在说Docker 镜像的原理知识之前我们先看下docker 容器和docker 镜像的区别因为这部分我们后面会涉及到。 简单说来我们可以将Docker 镜像看成是Docker 容器的静态时也可将Docker 容器看成是Docker镜像的运行时。 从Docker 的官方文档来看Docker 容器的定义和 Docker 镜像的定义几乎是相同Docker 容器和Docker 镜像的区别主要在于docker 容器多出了一个可写层。 容器中的进程就运行在这个可写层这个可写层有两个状态即运行态和退出态。当我们docker run 运行容器后docker 容器就进入了运行态当我们停止正在运行中的容器时docker 容器就进入了退出态。 我们将容器从运行态转为退出态时期间发生的变更都会写入到容器的文件系统中(需要注意的是此处不是写入到了docker 镜像中)这方面的变化下文中我们还会再细说。 Docker 存储简介 简单说来Docker 镜像就是一组只读的目录或者叫只读的 Docker 容器模板镜像中含有一个Docker 容器运行所需要的文件系统所以我们说Docker 镜像是启动一个Docker 容器的基础。 如果这样不是很好理解我们可以通过一个图一起看下从图中可以看出除了最上面的一层为读写层之外下面的其他的层都是只读的镜像层并且除了最下面的一层外其他的层都有会有一个指针指向自己下面的一层镜像。虽然统一文件系统(union file system)技术将不同的镜像层整合成一个统一的文件系统为构成一个完整容器镜像的层提供了一个统一的视角隐藏了多个层的复杂性对用户来说只存在一个文件系统但图中的这些层并不是不能看到的如果需要查看的话可以进入运行Docker的机器上进行查看从这些层中可以看到Docker 内部实现的一些细节接下来我们一起看下。 一般刚接触Docker 不久的话可能会不太清楚Docker 的存储方式是怎样的并且可能也不太清楚Docker 容器的镜像到底存储在什么路径下比较迷茫。 有些同学想了解下Docker 的镜像数据存储在什么位置然后谷歌了下几篇博文说是在/var/lib/docker 下有个aufs目录结果在自己机器上进到这个路径后发现没有aufs相关的目录然后以为是版本的问题其实不然。 以Linux服务器为例其实Docker 的容器镜像和容器本身的数据都存放在服务器的 /var/lib/docker/ 这个路径下。不过不同的linux发行版存储方式上有差别比如在ubuntu发行版上存储方式为AUFSCentOS发行版上的存储方式为device mapper。 /var/lib/docker 路径下的信息在不同的阶段会有变化从笔者个人经验来看了解这几个阶段中新增的数据以及容器与镜像的存储结构的变化非常有利于我们对Docker容器以及Docker镜像的理解。接下来我们一起看下Docker运行后、下载镜像后、运行容器后三个阶段中Docker 存储的变化。 环境信息 系统发行版CentOS7.2。内核版本3.10.0-327.36.1.el7.x86_64Docker 版本1.8启动Docker后 在此我们假设大家已经安装好了Docker环境具体安装的过程不再赘述。 # 启动Docker 服务 [rootinfluxdb ~]# systemctl start docker # 查看/var/lib/docker路径下的文件结构 [rootlocalhost docker]# tree .├── containers├── devicemapper│ ├── devicemapper│ │ ├── data│ │ └── metadata│ └── metadata│ ├── base│ ├── deviceset-metadata│ └── transaction-metadata├── graph├── linkgraph.db├── repositories-devicemapper├── tmp├── trust└── volumes 8 directories, 7 files 注必须启动Docker 服务后查看如果没有启动Docker 进程则路径/var/lib/docker 不存在。 前文中我们已经提到过CentOS发行版中Docker 服务使用的存储方式为devicemapper所以我们从前面tree命令的结果中可以看到出现了目录devicemapper。 有些同学可能会问什么是devicemapper 太阳底下无新鲜事devicemapper 并不是伴随着Docker 才出现的早在linux2.6版本的内核时其实就已经引入了devicemapper且当时是作为一个很重要的技术出现的。 简单说来devicemapper 就是Docker 服务的一个存储驱动或者叫Docker 服务的存储后端。Devicemapper 其实是一个基于内核的框架这个框架中对linux上很多的功能进行了增强比如对linux上高级卷管理功能的增强。Devicemapper 存储驱动将我们的每个docker镜像和docker容器都存在在自己的虚拟设备中devicemapper的这些设备相当于我们常见的一般的写时复制快照设备的超配版本。通过上面的介绍有些同学可能以为devicemapper 存储驱动是工作在块级别的但是devicempper 实际是工作在文件级别的也就是说devicemapper 存储驱动和写时复制操作都是直接操作块而不是对文件进行操作。 以上是我们关于Docker 服务的devicemapper 存储驱动的一个简单的介绍Docker 官方文档中提供了很多的有关Docker 存储驱动的介绍感兴趣的同学可以自行查阅。 进一步的查看的话可以看到路径/var/lib/docker/devicemapper下面有两个目录分别为devicemapper和data其中目录devicemapper 下存在两个名为data和metadata的文件两个文件从名称即可看出一个是镜像数据的存储池一个为镜像相关的元数据。接下去我们会逐个看下这个路径下的文件。 进入上面提到的目录metadata下可以看到这个目录中已经存在三个文件分别为base、deviceset-metadata和transction-metadata这三个文分别用来存放上文中我们提到的元数据的id、大小和uuid等信息。[rootlocalhost metadata]# pwd/var/lib/docker/devicemapper/metadata[rootlocalhost metadata]# lsbase deviceset-metadata transaction-metadata除了上面提到的几个目录上文中tree的结果中还有几个目录分别为containers、devicemapper、graph、linkgraph.db、repositories-devicemapper、tmp、trust和volumes。这几个文件对于docker 的镜像存储来说都很重要我们以文件repositories-devicemapper为例看下这个文件对于镜像存储所起到的作用。 [rootlocalhost docker]# pwd/var/lib/docker[rootlocalhost docker]# lscontainers devicemapper graph linkgraph.db repositories-devicemapper tmp trust volumes 我们可以先看下repositories-devicemapper 这个文件中在当前的阶段中有什么rootlocalhost docker]# cat repositories-devicemapper{Repositories:{}}[rootlocalhost docker]#从上面cat的结果中我们不难看出文件repositories-devicemapper 中其实记录的就是docker 镜像的属性信息比如镜像名称、镜像标签、镜像的ID等信息如果镜像刚好没有标签的话默认会以lastet作为标签。以上是对Docker 服务运行后pull镜像之前/var/lib/docker 路径下数据的一个简单的解读相信大家通过上面的描述已经对docker镜像有了一些更深入的认识。下面我们看下在我们pull 自己的第一个docker镜像之后路径/var/lib/docker 之下的数据会发生怎样的变化。 Pull 镜像后 在此我们以一个nginx镜像为例一起看下这个阶段的变化。 # pull 示例镜像[rootlocalhost docker]# docker pull nginxUsing default tag: latestlatest: Pulling from library/nginx22f3bf58cd09: Pull completeea2fc476f5f0: Pull complete81d728438afe: Pull complete303a6dec1190: Pull completed43816b44a22: Pull completedc02db50a25a: Pull complete6f650a34b308: Pull completea634e96a9de9: Pull complete72f3ebe1e4d7: Pull completec2c9e418b22c: Pull completeDigest: sha256:a82bbaf63c445ee9b854d182254c62e34e6fa92f63d7b4fdf6cea7e76665e06eStatus: Downloaded newer image for nginx:latest # 查看镜像是否已经在本地[rootlocalhost docker]# docker imagesREPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZEnginx latest c2c9e418b22c 2 weeks ago 109.3 MB[rootlocalhost docker]# 在此我们没有指定nginx镜像的tag因此默认拉去了最新的版本。然后我们看下路径/var/lib/docker 下是否有变化[rootlocalhost docker]# tree ..├── containers├── devicemapper│ ├── devicemapper│ │ ├── data│ │ └── metadata……省略若干数据……│ │ ├── checksum│ │ ├── json│ │ ├── layersize│ │ ├── tar-data.json.gz│ │ └── v1Compatibility│ ├── 303a6dec11900c97f5d7555d31adec02d2e5e4eaa1a77537e7a5ebd45bb7fcd2│ │ ├── checksum│ │ ├── json│ │ ├── layersize│ │ ├── tar-data.json.gz│ │ └── v1Compatibility│ ├── 6f650a34b3083c96cf8b7babc7a391227c0f78e0d07067071c46e31bd834de3a│ │ ├── checksum│ │ ├── json│ │ ├── layersize│ │ ├── tar-data.json.gz│ │ └── v1Compatibility│ ├── 72f3ebe1e4d793a50836d4e070c94ef7497c80111d178e867014981f64696a39│ │ ├── checksum│ │ ├── json│ │ ├── layersize│ │ ├── tar-data.json.gz│ │ └── v1Compatibility│ ├── 81d728438afe98602e2e692c20299ecf41b93173fb12351c1b59820b17fb16b9│ │ ├── checksum│ │ ├── json│ │ ├── layersize│ │ ├── tar-data.json.gz│ │ └── v1Compatibility│ ├── a634e96a9de9f1e280efaecdd43c7273ac43e109a42ab6c76ab2d2261c8cdc50│ │ ├── checksum│ │ ├── json│ │ ├── layersize│ │ ├── tar-data.json.gz│ │ └── v1Compatibility│ ├──……省略若干数据……│ ├── ea2fc476f5f055f9e44963987903ecfe0cb480b7e387d8b5cb64006832110afc│ │ ├── checksum│ │ ├── json│ │ ├── layersize│ │ ├── tar-data.json.gz│ │ └── v1Compatibility│ └── _tmp├── linkgraph.db├── repositories-devicemapper├── tmp├── trust└── volumes 30 directories, 67 files[rootlocalhost docker]# 从结尾的目录数和文件数也可以看出在我们拉取镜像后/var/lib/docker 下多出了很多的文件(拉取镜像之前只有8个目录7个文件)下面我们一步步的分析。 如果这个时候看下路径/var/lib/docker下的文件的话可以很容易的看到发生变化的主要是下面这三个文件/var/lib/docker/devicemapper/metadata、/var/lib/docker/devicemapper/mnt以及/var/lib/docker/graph。我们先看下metadata这个文件 从结果可以看出除了上一个阶段中已经有的base、deviceset-metadata等几个文件外还多出了一些名字较长的文件我们挨个看下这几个文件中的数据[rootlocalhost metadata]# cat base{device_id:1,size:107374182400,transaction_id:1,initialized:true} [rootlocalhost metadata]# cat 22f3bf58cd0949b57df2dc161e7026a8cc77699b6a8be7d0e3085e252a5439c3{device_id:2,size:107374182400,transaction_id:2,initialized:false}[rootlocalhost metadata]# cat ea2fc476f5f055f9e44963987903ecfe0cb480b7e387d8b5cb64006832110afc{device_id:3,size:107374182400,transaction_id:3,initialized:false} [rootlocalhost metadata]# cat 81d728438afe98602e2e692c20299ecf41b93173fb12351c1b59820b17fb16b9{device_id:4,size:107374182400,transaction_id:4,initialized:false} [rootlocalhost metadata]# cat d43816b44a2280148da8d9b6ce2f357bff9b2e59ef386181f36a4a433a9aad6c{device_id:6,size:107374182400,transaction_id:6,initialized:false} [rootlocalhost metadata]# cat 303a6dec11900c97f5d7555d31adec02d2e5e4eaa1a77537e7a5ebd45bb7fcd2{device_id:5,size:107374182400,transaction_id:5,initialized:false} [rootlocalhost metadata]# cat a634e96a9de9f1e280efaecdd43c7273ac43e109a42ab6c76ab2d2261c8cdc50{device_id:9,size:107374182400,transaction_id:9,initialized:false} [rootlocalhost metadata]# cat dc02db50a25a87ca227492197721e97d19f1822701fe3ec73533a0811a6393a7{device_id:7,size:107374182400,transaction_id:7,initialized:false} [rootlocalhost metadata]# cat 6f650a34b3083c96cf8b7babc7a391227c0f78e0d07067071c46e31bd834de3a{device_id:8,size:107374182400,transaction_id:8,initialized:false} [rootlocalhost metadata]# cat 72f3ebe1e4d793a50836d4e070c94ef7497c80111d178e867014981f64696a39{device_id:10,size:107374182400,transaction_id:10,initialized:false} [rootlocalhost metadata]# cat c2c9e418b22ca5a0b02ef0c2bd02c34ad792d1fc271e5580fdb3252979ccc092{device_id:11,size:107374182400,transaction_id:11,initialized:false} 从上面的结果可以看出上面的几个文件中的device_id数值是按照顺序排列下来的换句话说就是除了上一个阶段中已经存在的base文件上面结果中其他的几个文件都是nginx镜像的中间镜像层也就是我们经常执行的命令docker images –a 的结果中看到的构成当前镜像的各个镜像层。 接下来我们再看一个变化较大的文件/var/lib/docker/graph。 [rootlocalhost graph]# tree ..├── 22f3bf58cd0949b57df2dc161e7026a8cc77699b6a8be7d0e3085e252a5439c3│ ├── checksum│ ├── json│ ├── layersize│ ├── tar-data.json.gz│ └── v1Compatibility├── 303a6dec11900c97f5d7555d31adec02d2e5e4eaa1a77537e7a5ebd45bb7fcd2│ ├── checksum│ ├── json│ ├── layersize│ ├── tar-data.json.gz│ └── v1Compatibility├── 6f650a34b3083c96cf8b7babc7a391227c0f78e0d07067071c46e31bd834de3a│ ├── checksum│ ├── json│ ├── layersize│ ├── tar-data.json.gz│ └── v1Compatibility├── 72f3ebe1e4d793a50836d4e070c94ef7497c80111d178e867014981f64696a39│ ├── checksum│ ├── json│ ├── layersize│ ├── tar-data.json.gz│ └── v1Compatibility├── 81d728438afe98602e2e692c20299ecf41b93173fb12351c1b59820b17fb16b9│ ├── checksum│ ├── json│ ├── layersize│ ├── tar-data.json.gz│ └── v1Compatibility├── a634e96a9de9f1e280efaecdd43c7273ac43e109a42ab6c76ab2d2261c8cdc50│ ├── checksum│ ├── json│ ├── layersize│ ├── tar-data.json.gz│ └── v1Compatibility├── c2c9e418b22ca5a0b02ef0c2bd02c34ad792d1fc271e5580fdb3252979ccc092│ ├── checksum│ ├── json│ ├── layersize│ ├── tar-data.json.gz│ └── v1Compatibility├── d43816b44a2280148da8d9b6ce2f357bff9b2e59ef386181f36a4a433a9aad6c│ ├── checksum│ ├── json│ ├── layersize│ ├── tar-data.json.gz│ └── v1Compatibility├── dc02db50a25a87ca227492197721e97d19f1822701fe3ec73533a0811a6393a7│ ├── checksum│ ├── json│ ├── layersize│ ├── tar-data.json.gz│ └── v1Compatibility├── ea2fc476f5f055f9e44963987903ecfe0cb480b7e387d8b5cb64006832110afc│ ├── checksum│ ├── json│ ├── layersize│ ├── tar-data.json.gz│ └── v1Compatibility└── _tmp 11 directories, 50 files 从上面的结果中可以很明显的看到我们的镜像nginx及其每一个nginx镜像的中间层对应的目录下都包含如下几个文件checksum、json、layerrize、tar-data.json.gz和v1Compatibility。我们任意找一个文件看下这几个文件中存放了什么数据。 (1) Checksum 其实从文件名称即可看出每个镜像层中的checksum文件存放的是当前镜像层的md5值用于核对当前镜像层的数据是否完整。 (2) json 从cat 的结果中可以看出json文件中存放的数据较多比如Hostname、Domainname、User、Image等信息而且很多参数和我们经常接触的Dockerfile中的参数相似。相比较前面的checksum文件这个文件中的内容相对较复杂在此我们也解释下。 此处的json文件中一般主要用于存放镜像中涉及的动态信息但需要注意的是此处的json文件并不仅仅被用于存储docker镜像的动态信息(很多同学可能会认为此处的json文件只是被用来描述Docker容器的动态信息的)我们在使用Dockerfile 构建镜像时Dockerfile 构建过程中涉及到的所有操作基本都被记录到这个json文件中。 说到这儿有些同学可能会问这个json是在什么阶段被使用到的好问题。通过下面这个图我想大家应该就能看明白了 从图中我们可以看出每个镜像层的json文件其实是由Docker 守护进程进行解析的。Docker 守护进程通过json文件可以解析出运行容器需要的各种数据比如环境变量、workdir以及容器启动时需要执行的ENTRYPOINT或者CMD命令等。Docker 守护进程从json文件中获取到这些数据后接下来就开始进行容器进程的初始化。 (3) layersize 从文件名称即可看出这个文件中存放的为当前镜像层的占用空间大小 (4) repositories-devicemapper 上一阶段中我们解释过这个文件中记录的为当前镜像层的属性信息比如镜像名称信息、镜像标签信息、镜像的ID信息等 以上是对pull镜像之后运行容器之前镜像存储信息的简单介绍相信大家在看下之后对docker容器镜像已经有了更加深入的认识。下面我们看下本文中我们要说的最后一个阶段即运行容器后docker 的存储又发生了哪些变化。 运行容器后 我们运行下前面从dockerhub pull的镜像nginx:latest[rootlocalhost metadata]# docker imagesREPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZEnginx latest c2c9e418b22c 2 weeks ago 109.3 MB[rootlocalhost metadata]#[rootlocalhost metadata]#[rootlocalhost metadata]#[rootlocalhost metadata]# docker run --name nginx -d nginx:latest814ec80839669e235c94978ed3d07eab0e2b2bebd7d7a64fd6488cddca51be41[rootlocalhost metadata]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES814ec8083966 nginx:latest nginx -g daemon off 3 seconds ago Up 2 seconds 80/tcp nginx 按照惯例然后我们看下/var/lib/docker路径下的文件结构 和上一阶段不同这个阶段发生变化的文件主要是/var/lib/docker/devicemapper/metadata、/var/lib/docker/devicemapper/mnt以及/var/lib/docker/container下面我们逐个看下。 (1) metadata 我们看下metadata这个目录下的文件 从图中的结果可以看出相比上一个阶段当前阶段中metadata目录下多出了两个文件即以51be4e和51b44e-init结尾的两个文件。 我们都知道docker 借助容器镜像运行起容器之后会在当前镜像的最顶层添加一个特殊的层和其他的层相比这个层不但有可读的权限还有可写的权限。说到这相信多出的两个文件的功能就不难理解了。 (2) mnt 在查看mnt下的数据之前我们先看下这个目录下的文件结构 对比上面说过的metadata目录发现这两个目录下的文件是一样的相比前一个阶段的话也是新增了两个文件即以51be4e和51b44e-init结尾的两个文件。 (3) container 我们先看下当前目录下的文件结构 Container目录为容器本身的目录此目录中存放了诸如容器的配置文件等文件。如果我们删掉这个目录(docker 进程hang死导致docker rm、docker kill杀不掉容器时常用此种方式处理)的话正在运行的容器就会被删掉我们看下这几个文件都存放了什么数据。 (1) xxx.json.log、config.json从文件名称即可看出这两个文件存放的为当前容器的配置信息及其数据(2) hosts hosts配置信息在此不再赘述。 (3) hostname容器host名称可以cat查看后再进入容器查看hostname核对下看是否是一样的。 (4) resolv.confdns配置信息。 小结 前面分析了那么多涉及到docker 存储的文件在查阅各个文件或者目录作用时可能不是很方便在此我们给大家总结了一下各个文件的作用(每个文件都是在/var/lib/docker路径下) (1) devicemapper/devicemapper/data存储存储池相关的数据。(2) devicemapper/devicemapper/metdata存储元数据。(3) devicemapper/metadata/存储device_id、layersize等信息。(4) devicemapper/mnt存储挂载相关的信息。(5) container/存储容器本身的信息。(6) graph/存储各个镜像层的详细信息。(7) repositores-devicemapper存储镜像的一些基本信息。(8) tmp存储docker的临时目录。(9) trust存储docker的信任目录。(10) volumes存储docker的卷目录。福利扫描添加小编微信备注“姓名公司职位”加入【云计算学习交流群】和志同道合的朋友们共同打卡学习推荐阅读云计算之基一文带你速懂虚拟化KVM和XENOpenStack网络的下一步原来这么走 | 技术头条用一枚比特币环游世界? 他是不是疯了...程序员逆袭为美国最佳 CEO他说因为爱情斯坦福区块链匪帮传奇那些睡地毯、没日没夜写代码的编程少年Erlang 之父去世他留给程序员两点忠告开什么玩笑股票价格如何经得起AI的推敲| 技术头条真香朕在看了