【转】docker原理 range into docker

举报
Ragnar 发表于 2020/08/25 14:27:29 2020/08/25
【摘要】 这次主要想学习一下关于images,container 即容器和镜像之间的问题,理解了这些之后,对于docker命令也应该会有一些新的认识,毕竟了解原理才能了解一切。首先,docker利用的是统一文件系统(the union file system)来实现着关于容器和镜像的。看看这个wiki再回来看容器和镜像,会变得容易。所谓镜像,其实是一堆只读层的叠加,如图所示,左边有三个只读层,他们重叠...

这次主要想学习一下关于images,container 即容器和镜像之间的问题,理解了这些之后,对于docker命令也应该会有一些新的认识,毕竟了解原理才能了解一切。

首先,docker利用的是统一文件系统(the union file system)来实现着关于容器和镜像的。看看这个wiki再回来看容器和镜像,会变得容易。

所谓镜像,其实是一堆只读层的叠加,

image001.PNG

如图所示,左边有三个只读层,他们重叠在一起,除了最下面的一层,每一层都会有一个指针来指向下一层,这些在docker的内部是自己实现的,用户不感知。对普通用户来说,我们看到的是这三个可读层叠加之后的统一视角,即存在唯一一个对外的文件系统,就是右边所展示的形式。在运行中的容器,这些层是不可见的,但是在宿主机上可以找到这些层存在的痕迹,大概存在于/var/lib/docker下。


所谓容器,其实和镜像的定义是一致的,也是一堆layer的统一构建视角,不捅的是,对于顶层的layer,容器是一层可读写层。

image002.PNG


可以发现,容器的定义并没有定义它的状态,这是合理的,容器的定义其实只是 镜像+读写层,对于容器是不是运行其实是没有必要的。


下面来聊一聊运行中的容器,包含了可读写的统一文件系统(其实就是容器,也同时是镜像+读写层),加上利用namespace进行隔离的进程空间,和其中运行的各种进程。一个运行中的容器应该包括如下图所示的部分:

image003.PNG



namespace隔离是docker运行的基础,一个容器中的进程可能会对文件进行修改,这些改变,其实都作用于容器的可读写层,所以,当你在容器中touch了一个问题的时候,即使容器不在了,单你touch的文件还会在。


我们再往内部走远点,range!


上文提到,镜像是由一层一层的layer组成的,那么layer到底是什么呢?

image004.PNG


一个镜像层,不仅仅包括了文件系统的改变,还能包含其他的信息。镜像层中利用metadata提供关于这个层的额外信息,它不仅可以让docker获取运行时和构建时的信息,还包括父级层的相关信息。并且,不论是只读层还是读写层,都是包括metadata的。

一个运行中容器的metadata可以在/var/lib/docker/containers/<container-id>下找到,分成了很多数据,包括日志,设备等等。


有了上面的基础概念,现在可以理解一下docker各个指令的含义了:


docker create <image-id>

docker create 指令为指定的镜像(images)添加了一个可读写层,构成了一个新的容器,可以注意到,这个容器并没有运行。


docker start <container-id>

docker start 指令为一个容器制定了namespace隔离的进程空间,注意到,每个容器仅仅只能在一个进程空间中。


docker run <image-id>

docker run 其实是create 和 start指令合集,类似git push 和 git fetch git merge指令的含义差不多,run为images添加了一层读写层,并分配了一个进程空间给它运行。


docker ps

docker ps 列出了运行中的容器,检查进程隔离空间,并调出相应的容器最上层的信息。-a参数则会列出所有容器,不仅仅调查运行中的容器,列出所有容器的上层信息。


docker  images

该命令列出了所有top-level镜像,顶层镜像对外表现为整个镜像的信息。


docker stop <container-id>

stop命令会进程空间内的进程发送一个SIGTERM信号,然后终止所有的进程空间内的进程。


docker rm <container-id>

rm指令实际上只是移除了容器的可读写层,如果不加-f的话,只能对运行中的容器进行


docker rmi <image-id>

rmi移除了的top-level的只读层,可以利用-f来强制删除中间层。


docker commint <container-id>

commit指令把读写层转换成可读层,这样就完成了从容器(container)到镜像(images)的转换


docker build

这也是一个复合指令,它会反复执行很多命令:

build命令根据dockerfile文件中的FROM指令获取镜像,然后重复run(create & start)----->做一些修改和安装------> commit

在每一次的循环中,都会生成一个新的layer,因此许多新的layer都会被创建,最终,变成一个新的镜像。


docker exec <running-container-id>

该指令实际上是在运行容器外部的进程空间内执行相应的新进程


docker inspect <image-id>/<container-id>

该命令实际上提取了容器或者镜像的最顶层metadata


docker save <image-id>

save 命令会创造出一个镜像的压缩文件,这个文件可以被另一个机器上的docker使用,与export命令不同的是,这个命令把每一层都保存了metadata,因此这个命令只能对镜像生效。


docker export <container-id>

exprot 命令创建了一个压缩文件tar,并且移除了其中各层的metadata和没有必要的层,并将多个层整合成一个层,只保存了整合后的统一视角,如果export出来的奖项,再次improt到新的容器中,那么只能看到一个镜像,但是save出来的镜像不同,可以看到整个镜像的历史镜像。


docker history <image-id>

递归得出镜像的各个历史镜像




【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。