Answers:
我可能会迟到,但这是我的10美分(与ashishjain的回答相辅相成):
基本上,层或图像层是图像或中间图像的变化。您指定的每个命令(FROM
,RUN
,COPY
在你Dockerfile等)会导致之前的图像变化,从而创建一个新层。您可以在使用git时将其视为分段更改:添加文件的更改,然后添加另一个更改,然后添加另一个...
考虑以下Dockerfile:
FROM rails:onbuild
ENV RAILS_ENV production
ENTRYPOINT ["bundle", "exec", "puma"]
首先,我们选择一个起始图像:rails:onbuild
,它依次具有许多层。我们在起始图像的顶部添加另一层,RAILS_ENV
使用ENV
命令设置环境变量。然后,我们告诉docker运行bundle exec puma
(它将启动rails服务器)。那是另一层。
图层的概念在构建图像时派上用场。因为层是中间映像,所以如果您对Dockerfile进行更改,则docker将仅构建已更改的层以及之后的层。这称为层缓存。
您可以在此处了解更多信息。
https://labs.ctl.io/caching-docker-images/
)已损坏。有人建议更换吗?
使用dockerfile创建docker容器映像。dockerfile中的每一行都会创建一个图层。考虑下面的虚拟示例:
FROM ubuntu #This has its own number of layers say "X"
MAINTAINER FOO #This is one layer
RUN mkdir /tmp/foo #This is one layer
RUN apt-get install vim #This is one layer
这将创建最终图像,其中总层数将为X + 3
通过一个例子,它们对我来说最有意义。
让我们来看一个人为的Dockerfile示例:
FROM busybox
RUN mkdir /data
# imagine this is downloading source code
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one
RUN chmod -R 0777 /data
# imagine this is compiling the app
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/two
RUN chmod -R 0777 /data
# and now this cleans up that downloaded source code
RUN rm /data/one
CMD ls -alh /data
这些dd
命令中的每个命令都将一个1M文件输出到磁盘。让我们用一个额外的标记来构建图像以保存临时容器:
docker image build --rm=false .
在输出中,您将看到每个正在运行的命令都在我们现在保留的临时容器中发生,而不是自动删除:
...
Step 2/7 : RUN mkdir /data
---> Running in 04c5fa1360b0
---> 9b4368667b8c
Step 3/7 : RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one
---> Running in f1b72db3bfaa
1024+0 records in
1024+0 records out
1048576 bytes (1.0MB) copied, 0.006002 seconds, 166.6MB/s
---> ea2506fc6e11
如果您docker diff
在每个这些容器ID上运行,则会看到在这些容器中创建了哪些文件:
$ docker diff 04c5fa1360b0 # mkdir /data
A /data
$ docker diff f1b72db3bfaa # dd if=/dev/zero bs=1024 count=1024 of=/data/one
C /data
A /data/one
$ docker diff 81c607555a7d # chmod -R 0777 /data
C /data
C /data/one
$ docker diff 1bd249e1a47b # dd if=/dev/zero bs=1024 count=1024 of=/data/two
C /data
A /data/two
$ docker diff 038bd2bc5aea # chmod -R 0777 /data
C /data/one
C /data/two
$ docker diff 504c6e9b6637 # rm /data/one
C /data
D /data/one
每行前面带有,表示A
正在添加文件,C
表示对现有文件的更改,而D
表示删除。
上面的每个容器文件系统差异都进入一个“层”,当您将图像作为容器运行时,该“层”将被组装。进行添加或更改后,整个文件都位于每个层中,因此,这些chmod
命令中的每个命令(尽管只是更改了权限位)都导致整个文件被复制到下一层。删除的/ data / one文件仍在前一层中,实际上是3次,并且在拉取映像时将通过网络复制并存储在磁盘上。
您可以看到使用该命令创建现有图像图层的docker history
命令。您也可以docker image inspect
在图像上运行,然后在RootFS部分下查看图层列表。
这是上图的历史记录:
IMAGE CREATED CREATED BY SIZE COMMENT
a81cfb93008c 4 seconds ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "ls -… 0B
f36265598aef 5 seconds ago /bin/sh -c rm /data/one 0B
c79aff033b1c 7 seconds ago /bin/sh -c chmod -R 0777 /data 2.1MB
b821dfe9ea38 10 seconds ago /bin/sh -c dd if=/dev/zero bs=1024 count=102… 1.05MB
a5602b8e8c69 13 seconds ago /bin/sh -c chmod -R 0777 /data 1.05MB
08ec3c707b11 15 seconds ago /bin/sh -c dd if=/dev/zero bs=1024 count=102… 1.05MB
ed27832cb6c7 18 seconds ago /bin/sh -c mkdir /data 0B
22c2dd5ee85d 2 weeks ago /bin/sh -c #(nop) CMD ["sh"] 0B
<missing> 2 weeks ago /bin/sh -c #(nop) ADD file:2a4c44bdcb743a52f… 1.16MB
最新的层在顶部列出。值得注意的是,底部有两层相当古老的层。它们来自busybox映像本身。构建一幅图像时,将继承FROM
在行中指定的图像的所有层。还添加了用于更改图像元数据的图层,例如CMD
线条。它们几乎不占用任何空间,更多用于记录哪些设置适用于您正在运行的图像。
这些层具有几个优点。首先,它们是不可变的。创建后,由sha256哈希标识的图层将永远不会更改。这种不变性使图像可以安全地建立和分叉。如果两个dockerfile具有相同的初始行集并且构建在同一服务器上,则它们将共享相同的初始层集,从而节省磁盘空间。这也意味着如果您重建映像时,仅Dockerfile的最后几行发生更改,则仅需重建这些层,其余部分可以从层缓存中重用。这可以非常快速地重建docker映像。
在容器内,您会看到映像文件系统,但是该文件系统未复制。在这些图像层之上,容器会挂载它自己的读写文件系统层。每次读取文件都会遍历各个层,直到它到达标记该文件为要删除的层,在该层中具有该文件的副本或读取用完所有层以进行搜索为止。每次写入都会在特定于容器的读写层中进行修改。
这些层的一个缺点是构建可复制文件或运送在下一层删除的文件的图像。解决方案通常是将多个命令合并为一个RUN
命令。特别是在修改现有文件或删除文件时,希望这些步骤在最初创建它们的同一命令中运行。上面的Dockerfile的重写如下:
FROM busybox
RUN mkdir /data \
&& dd if=/dev/zero bs=1024 count=1024 of=/data/one \
&& chmod -R 0777 /data \
&& dd if=/dev/zero bs=1024 count=1024 of=/data/two \
&& chmod -R 0777 /data \
&& rm /data/one
CMD ls -alh /data
并且如果您比较结果图像:
只是通过将人为设计的示例中的几行合并在一起,我们在图像中得到了相同的结果内容,并将图像从5MB缩小到最终图像中看到的1MB文件。
从Docker v1.10开始,随着内容可寻址存储的引入,“层”的概念变得非常不同。层没有图像的概念或不属于图像,它们只是可以在图像之间共享的文件和目录的集合。层和图像变得分离。
例如,在从基础映像本地构建的映像上ubuntu:14.04
,该docker history
命令生成映像链,但是某些映像ID将显示为“丢失”,因为不再加载构建历史记录。组成这些图像的图层可以通过
docker inspect <image_id> | jq -r '.[].RootFS'
/var/lib/docker/aufs/diff
如果存储驱动程序选择为,则层内容存储在aufs
。但是这些层是用随机生成的缓存ID命名的,出于安全原因,似乎只有Docker Engine知道该层与其缓存ID之间的链接。我仍在寻找一种找出答案的方法
该博客提供了很多见识。
根据Docker 通过The Moby Project的图像规范:
图像由图层组成。每层都是一组文件系统更改。图层没有配置元数据,例如环境变量或默认参数-这些是整个图像的属性,而不是任何特定的图层。
因此,从本质上讲,一层只是对文件系统所做的一组更改。
"Each [Docker] layer is a set of filesystem changes."
(假设这是真的。)出于某种原因,当我阅读许多其他文档/时,我不理解这一基本要点。博客/ Q + A / etc,我怀疑限制是他们的,而不是我的。不管怎样,布拉迪·阿迪亚(Brity Aditya)赢得了问题的关注。
我认为官方文档给出了非常详细的解释:https : //docs.docker.com/engine/userguide/storagedriver/imagesandcontainers/。
(来源:docker.com)
映像由通常由Dockerfile生成的许多层组成,Dockerfile中的每一行都会创建一个新层,结果是一个映像,该映像由形式表示repo:tag
,例如ubuntu:15.04
。
有关更多信息,请考虑阅读上面的官方文档。
感谢@David Castillo提供有用的信息。我认为该层是可以轻松完成或撤消的图像二进制更改或指令。它们是与层上的层一样逐步完成的,因此我们称为“层”。
有关更多信息,您可以看到如下所示的“ docker history”:
码头工人图像-树 警告:'-tree'已过时,它将很快被删除。查看用法。 └─511136ea3c5a虚拟尺寸:0 B标签:刮擦:最新 └─59e359cb35ef虚拟大小:85.18 MB └─e8d37d9e3476虚拟大小:85.18 MB标签:debian:wheezy └─c58b36b8f285虚拟大小:85.18 MB └─90ea6e05b074虚拟大小:118.6 MB dc─5dc74cffc471虚拟大小:118.6 MB标签:vim:latest
我曾经认为它们就像前几层的差异。在阅读了一些答案之后,我不太确定。它们被描述为文件系统的一组更改。我已经写了一些Dockerfile来表明它们更像是diff,即它们确实依赖于先前的层。
给定这两个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
和
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...>
和
$ 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...>
您可以看到,即使在两种情况下对文件系统的更改相同,顺序也很重要。