我是Docker的新手,我正在努力理解Docker图像到底是什么。Docker映像的每个定义都使用术语“层”,但似乎并没有定义层的含义。

来自Docker官方文档:

我们已经看到Docker镜像是启动Docker容器的只读模板。每张图像都由一系列图层组成。Docker利用联合文件系统将这些层组合成单个映像。联合文件系统允许透明地覆盖独立文件系统(称为分支)的文件和目录,从而形成一个统一的文件系统。

所以我问,什么是层;有人能举几个具体的例子吗?这些图层是如何“合在一起”形成图像的呢?


当前回答

我可以给这个问题补充的是,你可以用git作为一个隐喻来理解层、图像和容器的概念。

事情是这样的:

A git repo crossponds to the image. Commit to a git repo crossponds to adding a layer. A git repo is started with git init on another hand an image build starts with the FROM. While you can use multiple FROM in multi stage builds, the concept stays the same since only the last FROM is used. A git repo is updated or based on a series of commits while an image is built by series of command/layers (excepts the CMD) of which each command creates a new layer of the image. Cloning and running a git repo corresponds to starting the container (CMD). Hence when cloning a git repo you typically clone the latest commit, while docker uses the latest created layer of the image when starting(docker run ...)

最后要注意的是,要理解层,很难将其视为一个孤立的概念,而应该将其视为使容器/图像工作的组件或构建块之一。类似地,commit是git版本控制系统的构建块之一,它可以被称为任何东西,而选择commit肯定是有意义的:)。

其他回答

我曾经认为它们就像前一层的差别。在阅读了这里的一些答案后,我不太确定;它们被描述为对文件系统的更改集。我写了一些dockerfile来说明它们更像差异文件,也就是说,它们确实依赖于前面的层。

给定这两个dockerfile

FROM bash
RUN mkdir /data
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/two
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/three

and

FROM bash
RUN mkdir /data
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/three
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/two
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one

如果它们只是关于文件系统的更改,人们会期望相同的层集,但事实并非如此:

$ docker history img_1
IMAGE               CREATED             CREATED BY                                      SIZE
30daa166a9c5        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
4467d16e79f5        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
c299561fd031        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
646feb178431        6 minutes ago       /bin/sh -c mkdir /data                          0B
78664daf24f4        2 weeks ago         /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>           2 weeks ago         /bin/sh -c #(nop)  ENTRYPOINT ["docker-entry…   0B
<more missing...>

and

$ docker history img_2
IMAGE               CREATED             CREATED BY                                      SIZE
f55c91305f8c        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
29b3b627c76f        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
18360be603aa        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
646feb178431        6 minutes ago       /bin/sh -c mkdir /data                          0B
78664daf24f4        2 weeks ago         /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>           2 weeks ago         /bin/sh -c #(nop)  ENTRYPOINT ["docker-entry…   0B
<more missing...>

您可以看到,即使在这两种情况下对文件系统的更改是相同的,顺序也很重要。

我个人的理解是我们可以将docker层与github提交进行比较。对于你的base image(你的fresh master repo),你做了几次提交,每一次提交都在改变你的master状态,这在docker中也是一样的,每一层都在做一些基于之前中间层的操作。然后,这一层成为下一层的新中间层。

我可以给这个问题补充的是,你可以用git作为一个隐喻来理解层、图像和容器的概念。

事情是这样的:

A git repo crossponds to the image. Commit to a git repo crossponds to adding a layer. A git repo is started with git init on another hand an image build starts with the FROM. While you can use multiple FROM in multi stage builds, the concept stays the same since only the last FROM is used. A git repo is updated or based on a series of commits while an image is built by series of command/layers (excepts the CMD) of which each command creates a new layer of the image. Cloning and running a git repo corresponds to starting the container (CMD). Hence when cloning a git repo you typically clone the latest commit, while docker uses the latest created layer of the image when starting(docker run ...)

最后要注意的是,要理解层,很难将其视为一个孤立的概念,而应该将其视为使容器/图像工作的组件或构建块之一。类似地,commit是git版本控制系统的构建块之一,它可以被称为任何东西,而选择commit肯定是有意义的:)。

根据Docker通过The Moby Project的图像规范:

图像由层组成。每一层都是一组文件系统 的变化。层没有配置元数据,比如环境 变量或默认参数-这些是图像的属性 一个整体,而不是任何特定的层。

因此,从本质上讲,一层只是对文件系统所做的一组更改。

我认为官方文件给出了非常详细的解释: https://docs.docker.com/engine/userguide/storagedriver/imagesandcontainers/。

(来源:docker.com)

image由很多层组成,这些层通常是从Dockerfile中生成的,Dockerfile中的每一行都将创建一个新的层,结果是一个image,用repo:tag的形式表示,如ubuntu:15.04。

欲了解更多信息,请考虑阅读上面的官方文档。