当前位置: 首页 > Linux

字节二:你的简历说你精通docker,你能告诉我容器和镜像之间的区别吗?

时间:2023-04-07 00:58:03 Linux

本文以图文并茂的方式介绍了容器和镜像的区别以及Docker每条命令背后的技术细节,帮助读者深入了解Docker。本文希望帮助读者更深入地了解Docker命令,以及容器和镜像的区别,探索容器和运行容器的区别。当我对Docker技术还是一知半解的时候,发现Docker命令的理解非常困难。于是,我花了几周的时间学习了Docker是如何工作的,更准确地说,学习了Docker统一文件系统(theunionfilesystem),然后回过头来看Docker命令,一切都变得合乎逻辑,非常简单。图像定义图像(Image)是一堆只读层(read-onlylayer)的统一透视图。也许这个定义有点难以理解。下图可以帮助读者理解图像的定义。从左边我们看到多个只读层相互重叠。除了底层,其他所有层都会有一个指向下一层的指针。这些层是Docker内部的实现细节,可以在宿主机(译者注:运行Docker的机器)的文件系统上访问。统一文件系统(unionfilesystem)技术可以将不同的层集成到一个文件系统中,并为这些层提供统一的视角,从而隐藏多层的存在。从用户的角度来看,只有一个文件系统。我们可以在图像的右侧以形式看到这个透视图。您可以在主机的文件系统上找到有关这些层的文档。请注意,这些层在正在运行的容器中是不可见的。在我的主机上,我发现它们存在于/var/lib/docker/aufs目录下。sudotree-L1/var/lib/docker//var/lib/docker/├──aufs├──containers├──graph├──init├──linkgraph.db├──repositories-aufs├──tmp├──trust└──volumes7个目录,2个文件ContainerDefinition容器(container)的定义和图像(image)的定义几乎一样,也是一层层堆叠的统一视角。唯一的区别是容器的顶层是可读可读的。书面。细心的读者可能会发现,容器的定义并没有提到容器是否在运行,是的,这是故意的。正是这个发现,让我明白了很多困惑。重要:容器=图像+可读层。并且容器定义没有说明是否运行容器。接下来,我们将讨论运行容器。运行容器定义运行容器定义为一个可读可写的统一文件系统加上一个隔离的进程空间和其中包含的进程。下图显示了一个运行中的容器。正是文件系统隔离使Docker成为如此有前途的技术。容器中的进程可能会修改、删除和创建文件,这些更改会影响读写层。下图演示了此行为。我们可以通过运行以下命令来验证我们上面所说的:dockerrunubuntutouchhappiness.txt即使ubuntu容器不再运行,我们仍然可以在主机的文件系统上找到这个新文件。find/-namehappiness.txt/var/lib/docker/aufs/diff/860a7b...889/happiness.txt图像层定义为了整合零星数据,我们提出了图像层(imagelayer)的概念。下图描述了一个镜像层。通过图片,我们可以发现,一个层中不仅包含了文件系统的变化,还包含了其他重要的信息。元数据(metadata)是关于这一层的附加信息,它不仅可以让Docker获得运行时和构建时的信息,还包括父层的层次信息。请注意,只读层和读写层都包含元数据。此外,每一层都包含一个指向父层的指针。如果某一层没有这个指针,则表示它在底层。元数据位置:我发现在我自己的主机上,镜像层的元数据存储在一个名为“json”的文件中,例如:/var/lib/docker/graph/e809f156dc985.../jsone809f156dc985...#This是这一层的id一个容器的元数据好像分了很多文件,但是在/var/lib/docker/containers/目录下或多或少都可以找到,而就是id一个可读层。该目录下的大部分文件都是运行时数据,比如网络、日志等。全局理解(TyingItAllTogether)现在,让我们结合上面提到的实现细节来理解Docker命令。dockercreatedockercreate命令为指定的镜像(image)添加一个可读写层,形成一个新的容器。请注意,此容器未运行。dockerstartDockerstart命令为容器文件系统创建一个进程隔离的空间。注意每个容器只能有一个进程隔离空间。dockerrun看到这个命令,读者通常会有一个疑问:dockerstart和dockerrun命令有什么区别。从图中可以看出,dockerrun命令首先使用镜像创建容器,然后运行容器。这个命令很方便,隐藏了两个命令的细节,但另一方面也很容易误导用户。dockerpsdockerps命令将列出所有正在运行的容器。这隐藏了非运行容器的存在,如果我们想找到这些容器,我们需要使用以下命令。dockerps–adockerps–a命令将列出所有容器,无论它们正在运行还是已停止。dockerimagesdockerimages命令会列出所有顶级(top-level)镜像。实际上,这里我们没有办法区分镜像和只读层,所以我们提出顶层镜像。只有创建容器时使用的镜像或者直接拉取的镜像才能称为顶层(top-level)镜像,每个顶层镜像隐藏了多个镜像层。dockerimages–adockerimages–a命令列出所有镜像,也可以说是列出所有可读层。如果想查看某个image-id下的所有层,可以使用dockerhistory查看。dockerstopdockerstop命令会向正在运行的容器发送一个SIGTERM信号,然后停止所有进程。dockerkilldockerkill命令向容器中运行的所有进程发送不友好的SIGKILL信号。dockerpausedockerstop和dockerkill命令会向正在运行的进程发送UNIX信号,但dockerpause命令不同。它利用cgroups的特性来暂停正在运行的进程空间。具体的内部原理可以在这里找到:https://www.kernel.org/doc/Doc...m.txt,但是这种方法的缺点是发送SIGTSTP信号不容易让进程理解,这样就不可能暂停所有进程。dockerrm![image]dockerrm命令删除构成容器的可读和可写层。请注意,此命令只能对未运行的容器执行。dockerrmidockerrmi命令删除构成图像的只读层。只能使用dockerrmi删除最顶层(或镜像),也可以使用-f参数强制删除中间的只读层。dockercommitdockercommit命令将容器的读写层转换为只读层,从而将容器转换为不可变镜像。dockerbuilddockerbuild命令很有意思,它会重复执行多个命令。从上图我们可以看出build命令是根据Dockerfile文件中的FROM指令获取镜像,然后重复1)run(创建并启动),2)修改,3)commit。循环中的每一步都会生成一个新层,因此创建了很多新层。dockerexecdockerexec命令将在正在运行的容器中执行一个新进程。dockerinspectdockerinspect命令将提取容器或图像的顶级元数据。dockersavedockersave命令将创建一个可以在另一台主机的Docker上使用的压缩图像文件。与导出命令不同,此命令保存每个图层的元数据。该命令只对镜像有效。dockerexportdockerexport命令创建一个tar文件,去掉元数据和不需要的层,将多个层整合为一层,只保存当前统一视角看到的内容(译者注:导入exoxt后的容器进入Docker,通过dockerimages–tree命令只能看到一个镜像;但是保存后的镜像不同,可以看到这个镜像的历史镜像)。dockerhistorydockerhistory命令递归输出指定镜像的历史镜像。更多Docker命令请参考文章:这20条Docker命令你知道几个?作者:bethal来源:https://www.cnblogs.com/betha...