开发者社区> 华章计算机> 正文

《Docker进阶与实战》——3.3节Docker image的组织结构

简介:
+关注继续查看

本节书摘来自华章社区《Docker进阶与实战》一书中的第3章,第3.3节Docker image的组织结构,作者华为Docker实践小组,更多章节内容可以访问云栖社区“华章社区”公众号查看

3.3 Docker image的组织结构
上节讲到Docker image是用来启动容器的只读模板,提供容器启动所需要的rootfs,那么Docker是怎么组织这些数据的呢?

3.3.1 数据的内容
Docker image包含着数据及必要的元数据。数据由一层层的image layer组成,元数据则是一些JSON文件,用来描述数据(image layer)之间的关系以及容器的一些配置信息。下面使用overlay存储驱动对Docker image的组织结构进行分析,首先需要启动Docker daemon,命令如下:

# docker daemon -D –s overlay –g /var/lib/docker

这里从官方镜像库下载busybox镜像用作分析。由于前面已经下载过该镜像,所以这里并没有重新下载,而只是做了简单的校验。可以看到Docker对镜像进行了完整性校验,这种完整性的凭证是由镜像仓库提供的。相关内容会在后面的章节提到,这里不再展开
介绍。

$ docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
cf2616975b4a: Already exists 
8c2e06607696: Already exists 
Digest: sha256:38a203e1986cf79639fb9b2e1d6e773de84002feea2d4eb006b52004ee8502d
Status: Image is up to date for busybox:latest
$  docker history busybox      #为了排版对结果做了一些整理
IMAGE                CREATED           CREATED BY                   SIZE
8c2e06607696     4 months ago                                       0 B
6ce2e90b0bc7     4 months ago      /bin/sh -c #(nop) ADD file        2.43 MB
cf2616975b4a     4 months ago      /bin/sh -c #(nop) MAINTAINER     0 B
该镜像包含cf2616975b4a、6ce2e90b0bc7、 8c2e06607696三个layer。让我们先到本地存储路径一探究竟吧。
# ls  -l /var/lib/docker
total 44
drwx------ 2 root root 4096 Jul 24 18:41 containers           #存放容器运行相关信息
drwx------ 3 root root 4096 Apr 13 14:32 execdriver 
drwx------ 6 root root 4096 Jul 24 18:43 graph                #Image各层的元数据
drwx------ 2 root root 4096 Jul 24 18:41 init
-rw-r--r-- 1 root root 5120 Jul 24 18:41 linkgraph.db
drwxr-xr-x 5 root root 4096 Jul 24 18:43 overlay              #Image各层数据
-rw------- 1 root root  106 Jul 24 18:43 repositories-overlay #Image总体信息
drwx------ 2 root root 4096 Jul 24 18:43 tmp
drwx------ 2 root root 4096 Jul 24 19:09 trust                #验证相关信息
drwx------ 2 root root 4096 Jul 24 18:41 volumes              #数据卷相关信息

1.总体信息
从repositories-overlay文件可以看到该存储目录下的所有image以及其对应的layer ID。为了减少干扰,实验环境之中只包含一个镜像,其ID为8c2e06607696bd4af,如下。

# cat repositories-overlay  |python -m json.tool
{
"Repositories": {
    "busybox": {
        "latest": "8c2e06607696bd4afb3d03b687e361cc43cf8ec1a4a725bc96e39f05ba97dd55"
            }
        }
}

2.数据和元数据
graph目录和overlay目录包含本地镜像库中的所有元数据和数据信息。对于不同的存储驱动,数据的存储位置和存储结构是不同的,本章不做深入的讨论。可以通过下面的命令观察数据和元数据中的具体内容。元数据包含json和layersize两个文件,其中json文件包含了必要的层次和配置信息,layersize文件则包含了该层的大小。

# ls -l graph/8c2e06607696bd4afb3d03b687e361cc43cf8ec1a4a725bc96e39f05ba97dd55/
total 8
-rw------- 1 root root 1446 Jul 24 18:43 json       
-rw------- 1 root root    1 Jul 24 18:43 layersize  
# ls -l overlay/8c2e06607696bd4afb3d03b687e361cc43cf8ec1a4a725bc96e39f05ba97dd55/
total 4
drwxr-xr-x 17 root root 4096 Jul 24 18:43 root

可以看到Docker镜像存储路径下已经存储了足够的信息,Docker daemon可以通过这些信息还原出Docker image:先通过repositories-overlay获得image对应的layer ID;再根据layer对应的元数据梳理出image包含的所有层,以及层与层之间的关系;然后使用联合挂载技术还原出容器启动所需要的 rootfs和一些基本的配置信息。

3.3.2 数据的组织
从上节看到,通过repositories-overlay可以找到某个镜像的最上层layer ID,进而找到对应的元数据,那么元数据都存了哪些信息呢?可以通过docker inspect得到该层的元数据。为了简单起见,下面的命令输出中删除了一些与讨论无关的层次信息。

意 docker inspect并不是直接输出磁盘中的元数据文件,而是对元数据文件进行了整理,使其更易读,比如标记镜像创建时间的条目由created改成了Created;标记容器配置的条目由container_config改成了ContainerConfig,但是两者的数据是完全一致的。

$ docker inspect busybox:latest
[
{
    "Id": "8c2e06607696bd4afb3d03b687e361cc43cf8ec1a4a725bc96e39f05ba97dd55",
    "Parent": "6ce2e90b0bc7224de3db1f0d646fe8e2c4dd37f1793928287f6074bc451a57ea",
    "Comment": "",
    "Created": "2015-04-17T22:01:13.062208605Z",
    "Container": "811003e0012ef6e6db039bcef852098d45cf9f84e995efb93a176a11e9aca6b9",
    "ContainerConfig": {
        "Hostname": "19bbb9ebab4d",
        "Domainname": "",
        "User": "",
        "AttachStdin": false,
        "AttachStdout": false,
        "AttachStderr": false,
        "ExposedPorts": null,
        "PublishService": "",
        "Tty": false,
        "OpenStdin": false,
        "StdinOnce": false,
        "Env": null,
        "Cmd": [
            "/bin/sh",
            "-c",
            "#(nop) CMD [\"/bin/sh\"]"
        ],
    "DockerVersion": "1.6.0",
    "Author": "Jevome Petazzoni \u003cjerome@docker.com\u003e",
    "Config": {
        "Hostname": "19bbb9ebab4d",
        "Domainname": "",
        "User": "",
        "AttachStdin": false,
        "AttachStdout": false,
        "AttachStderr": false,
        "ExposedPorts": null,
        "PublishService": "",
        "Tty": false,
        "OpenStdin": false,
        "StdinOnce": false,
        "Env": null,
        "Cmd": [
            "/bin/sh"
        ],
    "Architecture": "amd64",
    "Os": "linux",
    "Size": 0,
    "VirtualSize": 2433303,
    "GraphDriver": {
        "Name": "aufs",
        "Data": null
    }
}
]

对于上面的输出,有几项需要重点说明一下:
Id:Image的ID。通过上面的讨论,可以看到image ID实际上只是最上层的layer ID,所以docker inspect也适用于任意一层layer。
Parent:该layer的父层,可以递归地获得某个image的所有layer信息。
Comment:非常类似于Git的commit message,可以为该层做一些历史记录,方便其他人理解。
Container:这个条目比较有意思,其中包含哲学的味道。比如前面提到容器的启动需要以image为模板。但又可以把该容器保存为镜像,所以一般来说image的每个layer都保存自一个容器,所以该容器可以说是image layer的“模板”。
Config:包含了该image的一些配置信息,其中比较重要的是:“env”容器启动时会作为容器的环境变量;“Cmd”作为容器启动时的默认命令;“Labels”参数可以用于docker images命令过滤。
Architecture:该image对应的CPU体系结构。现在Docker官方支持amd64,对其他体系架构的支持也在进行中。
通过这些元数据信息,可以得到某个image包含的所有layer,进而组合出容器的rootfs,再加上元数据中的配置信息(环境变量、启动参数、体系架构等)作为容器启动时的参数。至此已经具备启动容器必需的所有信息。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
23533 0
进阶实战02-基于ECS快速搭建Docker环境
部署Docker环境,并使用Docker安装Nginx服务
546 0
课程干货免费学!一起解读Spring Cloud微服务架构设计与开发实战(第一期)
阿里云开发者学堂全员开课计划上线!阿里云开发者学堂将为开发者提供超多免费Java精品课!本次干货总结了——Java Spring Cloud微服务实战课时课程内容 。阿里云开发者学堂是开发者学习成长的一站式学习平台,为开发者构建完善的学习成长体系、技术赋能。Java Spring Cloud是全球范围内成熟、完善、流行的微服务架构方案体系,被众多的互联网大公司采用,包括阿里巴巴、腾讯、支付宝、网易、IBM、谷歌、京东、百度、滴滴等。为给同学带来最佳学习效果,课程文字、课程链接、图谱地址统统为大家放送了哦!
322 0
docker进阶与实战 4 仓库进阶
repository集中存储镜像,支持镜像分发及更新,后端存储常采用分布式,解决容灾问题. 官方仓库是docker hub,其中又有许多名称相同,内容不同的子仓库. 关系为:hub{repository{images}} 完整的仓库包括镜像存储系统和账户管理系统.
927 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
20048 0
10057
文章
0
问答
来源圈子
更多
+ 订阅
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载