跟我学Docker:docker镜像的分层(十)

1,564
原文链接: www.sudo.ren

分层存储

因为镜像包含操作系统完整的 root 文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。

  镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。

  分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。

为了给大家更好的说明docker分层,我简单的画了个图:
这样是不是就更容易明白。
接下来我们通过查看已经使用过的镜像,看看建立了多少层。
[root@docker01 kod]# docker image history kod:v1
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
0cb8570501c2        4 hours ago         /bin/sh -c #(nop)  CMD ["/bin/bash" "/init.s…   0B                  
b3c16a974832        4 hours ago         /bin/sh -c #(nop)  EXPOSE 80                    0B                  
3accb1a39dec        4 hours ago         /bin/sh -c #(nop) ADD file:d2eb5832a79974baa…   71B                 
b2da41f6de39        4 hours ago         /bin/sh -c chmod -R 777 /var/www/html           46.4MB              
3fafe7686735        4 hours ago         /bin/sh -c unzip kodexplorer.zip                32.5MB              
0f2e23c07571        4 hours ago         /bin/sh -c #(nop) COPY file:1c1d7e056dad265c…   13.9MB              
2d82050d0c64        4 hours ago         /bin/sh -c #(nop) WORKDIR /var/www/html         0B                  
258d58cc840e        4 hours ago         /bin/sh -c yum install httpd php php-cli unz…   137MB               
2199b8eb8390        4 months ago        /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
<missing>           4 months ago        /bin/sh -c #(nop)  LABEL name=CentOS Base Im…   0B                  
<missing>           4 months ago        /bin/sh -c #(nop) ADD file:0e6d175401c5b4260…   195MB               
[root@docker01 kod]# 

上面是我们在前面做的可道云网盘,可以看见有6次数据变动(size >0B,即为数据变动),因此可以判定该镜像kod已经有6曾,为了更好的证实,我们直接去看看镜像的层数。

进入/var/lib/docker/image/overlay2(docker镜像存储默认位置)执行tree命令,在执行tree命令之前,我们需要先将额外的镜像都删掉,否则tree出来就会有很多层级,不容易找到我们想要的kod镜像的信息。

[root@docker01 overlay2]# pwd
/var/lib/docker/image/overlay2
[root@docker01 overlay2]# tree
.
├── distribution
    .
    .
    .
├── imagedb
    .
    .
    .
├── layerdb
│   ├── mounts
│   ├── sha256
│   │   ├── 3ef205072ac5db56ae4cd548637ba87140ea3a19e20b2b47ab1e0af81b1ad2dc
│   │   │   ├── cache-id
│   │   │   ├── diff
│   │   │   ├── parent
│   │   │   ├── size
│   │   │   └── tar-split.json.gz
│   │   ├── 6547e4ebf8b9004b4ad7f111d2934c02b29ac1022f641dcf0bcbe8994731daae
│   │   │   ├── cache-id
│   │   │   ├── diff
│   │   │   ├── parent
│   │   │   ├── size
│   │   │   └── tar-split.json.gz
│   │   ├── 65a634b751557cd918a27361fe5c24737df737c6d96cfd1b159b188d0531dd5d
│   │   │   ├── cache-id
│   │   │   ├── diff
│   │   │   ├── parent
│   │   │   ├── size
│   │   │   └── tar-split.json.gz
│   │   ├── 6f01adb2c832d8faeb45b06a17bf5f1dfe125c64c7807cd398bf4f7ef4ad7d26
│   │   │   ├── cache-id
│   │   │   ├── diff
│   │   │   ├── parent
│   │   │   ├── size
│   │   │   └── tar-split.json.gz
│   │   ├── aaa5621d7c0157cae5916c9cca66dd8fc2fb4bdb74813ed463b73d5b58cccfdf
│   │   │   ├── cache-id
│   │   │   ├── diff
│   │   │   ├── size
│   │   │   └── tar-split.json.gz
│   │   └── f90436d76d1b9e69bf3ac779703209988e1f4d9c88195ec819b69fc732fd11f7
│   │       ├── cache-id
│   │       ├── diff
│   │       ├── parent
│   │       ├── size
│   │       └── tar-split.json.gz
│   └── tmp
└── repositories.json

28 directories, 62 files
[root@docker01 overlay2]# 

可以看见在layerdb-sha256,有6个分层。

docker为什么要分层呢?

分层的好处:共享资源,节省资源 有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。

docker总结:

其实这一章我将的并不太好,希望大家下手轻点,骂我可以,别骂我家人,啊哈哈哈。