什么是层次?

Docker 容器是应用程序的构建块。每个容器都是一个镜像,在一堆只读层之上有一个可读/可写层

这些层(也称为中间镜像)是在 Docker 镜像构建期间执行 Dockerfile 中的命令时生成的

例如,这是一个用于创建 node.js Web 应用程序镜像的 Dockerfile。它显示了为创建镜像而执行的命令


FROM node:argon
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install
# Bundle app source
COPY . /usr/src/app
EXPOSE 8080
CMD [ "npm", "start" ]

如下图,当Docker从上面的Dockerfile构建容器时,每一步都对应着Dockerfile中运行的一个命令。 每层都由运行该命令生成的文件组成。 随着每一步,创建的层被列出,由其随机生成的 ID 表示。 例如,步骤 1 的层 ID 为 530c750a346e。

$ docker build -t expressweb .
Step 1 : FROM node:argon
argon: Pulling from library/node...
...
Status: Downloaded newer image for node:argon
 ---> 530c750a346e
Step 2 : RUN mkdir -p /usr/src/app
 ---> Running in 5090fde23e44
 ---> 7184cc184ef8
Removing intermediate container 5090fde23e44
Step 3 : WORKDIR /usr/src/app
 ---> Running in 2987746b5fba
 ---> 86c81d89b023
Removing intermediate container 2987746b5fba
Step 4 : COPY package.json /usr/src/app/
 ---> 334d93a151ee
Removing intermediate container a678c817e467
Step 5 : RUN npm install
 ---> Running in 31ee9721cccb
 ---> ecf7275feff3
Removing intermediate container 31ee9721cccb
Step 6 : COPY . /usr/src/app
 ---> 995a21532fce
Removing intermediate container a3b7591bf46d
Step 7 : EXPOSE 8080
 ---> Running in fddb8afb98d7
 ---> e9539311a23e
Removing intermediate container fddb8afb98d7
Step 8 : CMD npm start
 ---> Running in a262fd016da6
 ---> fdd93d9c2c60
Removing intermediate container a262fd016da6
Successfully built fdd93d9c2c60

构建镜像后,您可以使用 docker history 命令查看构成镜像的所有层。 image 列(即中间镜像或层)显示与该层相关的随机生成的 UUID

docker history <image>
$ docker history expressweb
IMAGE         CREATED    CREATED BY                       SIZE      
fdd93d9c2c60  2 days ago /bin/sh -c CMD ["npm" "start"]   0 B
e9539311a23e  2 days ago /bin/sh -c EXPOSE 8080/tcp       0 B
995a21532fce  2 days ago /bin/sh -c COPY dir:50ab47bff7   760 B
ecf7275feff3  2 days ago /bin/sh -c npm install           3.439 MB
334d93a151ee  2 days ago /bin/sh -c COPY file:551095e67   265 B
86c81d89b023  2 days ago /bin/sh -c WORKDIR /usr/src/app  0 B
7184cc184ef8  2 days ago /bin/sh -c mkdir -p /usr/src/app 0 B
530c750a346e  2 days ago /bin/sh -c CMD ["node"]          0 B

当执行 docker run 命令时,一个镜像就变成了一个容器。

docker run expressweb

下图是通过 run 命令创建的容器的示意图。 容器有一个可写层,堆叠在镜像层之上。 这个可写层允许您对容器进行“更改”,因为镜像中的较低层是只读的。

image.png

层在哪里找到?

要深入了解镜像的每一层并查看其内容,您需要在 Docker 主机上查看层:

/var/lib/docker/aufs

如果在 OSX 上运行 Docker,则 Docker 主机实际上是一个名为 docker machine 的 linux 虚拟机。 在 OSX 上,您可以 ssh 进入 docker 机器以查看 aufs 目录:

$ docker-machine ssh default
                        ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /"""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/
 _                 _   ____     _            _
| |__   ___   ___ | |_|___ \ __| | ___   ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|   <  __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
Boot2Docker version 1.12.3, build HEAD : 7fc7575 - Thu Oct 27 17:23:17 UTC 2016
Docker version 1.12.3, build 6b644ec
docker@default:~$ df -h
Filesystem   Size    Used Available Use% Mounted on
tmpfs      896.2M  192.1M 704.1M 21% /
tmpfs      497.9M       0  497.9M 0% /dev/shm
/dev/sda1   17.9G    2.4G   14.6G 14% /mnt/sda1
cgroup     497.9M       0  497.9M 0% /sys/fs/cgroup
Users      464.8G  110.0G  354.8G 24% /Users
/dev/sda1   17.9G    2.4G   14.6G 14% /mnt/sda1/var/lib/docker/aufs

docker@default:~$ ls /mnt/sda1/var/lib/docker/aufs
diff    layers  mnt

/var/lib/docker/aufs 目录指向另外三个目录:diff、layers 和 mnt。

  • 镜像层及其内容存储在 diff 目录中。
  • 镜像层的堆叠方式位于层目录中。
  • 正在运行的容器挂载在 mnt 目录下(下面将详细解释挂载)

为了更好地了解层是如何工作的,我认为讨论 AUFS 存储驱动程序很有趣。 如果你不熟悉这个,这里有几个我认为很高兴知道的关键词:

  • Union Mount 是一种将多个目录组合到一个目录中的方法,该目录看起来包含所有目录的内容。
  • AUFS 代表另一个联合文件系统或高级多层统一文件系统(从版本 2 开始)。 AUFS 为 Linux 文件系统实现了联合挂载。
  • AUFS 存储驱动程序使用联合挂载系统实现 Docker 镜像层。
  • AUFS 分支——每个 Docker 镜像层被称为一个 AUFS 分支。

使用 Union 文件系统非常酷,因为它们将每个镜像层的所有文件合并在一起,并在 union 挂载点将它们呈现为一个只读目录。 如果不同层有重复文件,则显示上一层的文件。

我非常喜欢下面显示的 Docker 文档中的一个镜像,它将 Ubuntu 镜像的每一层显示为一个 AUFS 分支,以及它的文件存储在联合文件系统中的 Docker 主机上的位置。 此外,它还将这些层显示为可写容器层中公开的联合挂载点中的统一视图。

image.png

为什么要为 Docker 使用联合挂载系统?

使用联合文件系统允许创建的每个层被无限数量的镜像重复使用。 这节省了大量磁盘空间并允许更快地构建镜像,因为它只是重新使用现有层。 此外,读/写顶层提供了可以修改镜像的外观,但下面的只读层实际上通过隔离文件系统的内容来保持容器的完整性。

作为节省磁盘空间的一个例子,我总是希望将我的 docker 镜像设计得尽可能轻。 假设我需要为我的 Web 应用程序的日志文件创建一个命名的数据卷容器。 我想到的第一件事是,我可以使用什么基础镜像来使这个体积容器的重量最轻。 我决定使用 tianon/true image 因为它是 125 字节的超轻量级。 但后来我记得我正在为我的网络应用程序使用 Ubuntu 基础。 因此,如果我已经有一个 Ubuntu 镜像,实际上最好只为我的数据卷容器重用该基本镜像,而不是使用 tianon/true 创建更多层。

点赞(0)

评论列表 共有 0 评论

暂无评论

微信服务号

微信客服

淘宝店铺

support@elephdev.com

发表
评论
Go
顶部