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

来自Docker官方文档:

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

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


当前回答

我可能会迟到,但以下是我的看法(补充ashishjain的回答):

基本上,一个层,或图像层是图像或中间图像的变化。你在Dockerfile中指定的每个命令(FROM, RUN, COPY等)都会导致之前的图像发生变化,从而创建一个新层。在使用git时,您可以将其视为阶段性更改:添加一个文件的更改,然后是另一个文件,然后是另一个文件……

考虑下面的Dockerfile:

FROM rails:onbuild
ENV RAILS_ENV production
ENTRYPOINT ["bundle", "exec", "puma"]

首先,我们选择一个起始映像:rails:onbuild,它又有许多层。 我们在开始的图像上添加另一个层,使用ENV命令设置环境变量RAILS_ENV。然后,我们告诉docker运行bundle exec puma(这会启动rails服务器)。这是另一层。

层的概念在构建图像时派上了用场。因为图层是中间图像,如果你对Dockerfile做了更改,docker将只重建被更改的层和之后的层。这被称为层缓存。

你可以在这里阅读更多信息。

其他回答

我可能会迟到,但以下是我的看法(补充ashishjain的回答):

基本上,一个层,或图像层是图像或中间图像的变化。你在Dockerfile中指定的每个命令(FROM, RUN, COPY等)都会导致之前的图像发生变化,从而创建一个新层。在使用git时,您可以将其视为阶段性更改:添加一个文件的更改,然后是另一个文件,然后是另一个文件……

考虑下面的Dockerfile:

FROM rails:onbuild
ENV RAILS_ENV production
ENTRYPOINT ["bundle", "exec", "puma"]

首先,我们选择一个起始映像:rails:onbuild,它又有许多层。 我们在开始的图像上添加另一个层,使用ENV命令设置环境变量RAILS_ENV。然后,我们告诉docker运行bundle exec puma(这会启动rails服务器)。这是另一层。

层的概念在构建图像时派上了用场。因为图层是中间图像,如果你对Dockerfile做了更改,docker将只重建被更改的层和之后的层。这被称为层缓存。

你可以在这里阅读更多信息。

图层是包含文件和文件夹的文件夹,这些文件和文件夹是创建图像的结果。

例如:

FROM alpine:3.14            # Layer 1
RUN apk add --no-cache tree # Layer 2
COPY test.txt /tmp/         # Layer 3
ENTRYPOINT ["tree"]

这个Dockerfile将创建三个文件夹,然后将它们复制到主机系统并“合并”在一起,创建所谓的联合文件系统。这些文件夹实际上并没有在物理上合并,但是使用了Union Mount来创建它们合并的假象。

在上面的例子中,会有:

# Layer 1
/var/lib/docker/overlay2/1d06...35310/diff
bin    dev    etc    home   lib    media  mnt    opt    proc   root   run    sbin   srv    sys    tmp    usr    var

# Layer 2
/var/lib/docker/overlay2/23wgom2anm2uysvg988r3tw9c/diff
etc  lib  usr  var
           bin
             tree

# Layer 3
/var/lib/docker/overlay2/41htpkg76b3zwg29kqsb103of/diff
tmp
 test.txt

然后使用前面提到的mount命令“合并”所有这些文件夹,创建最终的Linux文件系统,然后使用chroot命令或类似命令将其设置为正在运行的进程(也就是容器)的根目录(在本例中为“树”)。

更多信息可以在这里找到:https://martinheinz.dev/blog/44

自Docker v1.10以来,随着内容可寻址存储的引入,“层”的概念变得非常不同。图层没有图像或属于图像的概念,它们只是可以在图像之间共享的文件和目录的集合。图层和图像被分离。

例如,在一个从基础映像本地构建的映像上,比如说ubuntu:14.04, docker history命令会生成映像链,但是有些映像id会显示为'missing',因为构建历史不再加载。组成这些图像的图层可以通过

docker inspect <image_id> | jq -r '.[].RootFS'

如果存储驱动选择为aufs,则层内容存储在/var/lib/docker/aufs/diff。但是这些层是用一个随机生成的缓存ID命名的,似乎只有出于安全考虑,Docker引擎才知道层和它的缓存ID之间的链接。我还在想办法弄清楚

图像与其构成层之间的对应关系 磁盘上层的实际位置和大小

这个博客提供了很多见解。

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

(来源:docker.com)

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

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

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

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

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