Loading

Docker镜像浅谈

先抛出几个我在学习过程中产生的几个问题.

1. 容器镜像是什么和装系统时的镜像有什么关系?

2. 容器镜像的作用是什么?

3. 不同版本的ubuntu镜像有什么区别比如说 ubuntu:18.04ubuntn:16.04 的区别?

4. Docker镜像为什么要分层每层都包含什么什么时候会创建新的一层 ? 每层的权限是如何配置的只有最底层的镜像层是只读的吗?
 

1 Docker镜像之初见

1.1 什么是镜像

      使用docker pull <image name>下载一个镜像看看

 

      可以看到我们仅仅是pull了一个ubuntu18.04的镜像, docker pull的结果却出现了多行这是因为镜像是分成多层的具体为什么要分层每一层又是什么下文我们会谈到.

      由于docker 18.04采用的是overlayfs2作为默认的存储驱动所以下载的镜像都存储在/var/lib/docker/overlay2 .

 

     可以看到这里的目录个数和镜像层数是一致并且除了0c开头的那一层其他目录都是有diffwork两个子目录 . 0c开头的目录就是整个镜像最底层的只读层 

l目录下全部都是指向这些diff目录的软链接.让我们进入0c.../diff中看看可以看到在diff目录中是一套完整的根目录所以说本质上根目录就是一个rootfs. 

跟装系统时的镜像没有一点点关系.

 

1.2 构建Docker镜像

     本节来说说如何使用使用Dockerfile构建自己的镜像, dockfile由一系列的命令构成。我目前用过的有FROM RUN CMD ADD COPY命令。

     From用来制定一个基础镜像层。

     RUN命令会在一个新的镜像层上执行参数中所指定的任何命令commit命令的执行结果。

     CMD命令在我初次使用时RUN有所混淆但是其实二者是完全不同的, CMD只是指定了运行容器时的初始命令但是在镜像构建时没有commit任何命令的结果。

举例来说下图是一个Dockerfile. 在其中我们先在一个新的镜像层创建一个shell脚本然后在CMD中运行这个脚本。

 

 

      可以看到容器执行CMD中指定的命令.

2 镜像的特性

2.1 分层特性

  在我们使用docker run命令启动一个容器时就会在现有的只读镜像层之上在创建一个可读写的容器层. 当我们将这些容器删除时这些容器层也会被删除

但是容器层之下的镜像层却不会改变.

 图盗自(docker reference)

 

 

通过这种共享相同的镜像层的方式, 容器即实现了一定的隔离(容器层之间), 又节省了空间.

2.2 写时拷贝(COW)

      如果容器需要读底层的文件或者目录那么直接读取底层的文件但是如果容器需要修改底层的文件那么容器层就会拷贝一个底层的文件.

虽说都是COW策略但是实现起来不同的存储驱动也是有所不同的.

      以overlayfs/overlayfs2为例:

    1. 搜索所有的镜像层找到要修改的文件这个过程从最新的一层直到最底层另外搜索结果会放到缓存中加速下一次的查找。

    2. 执行copy_up操作将文件拷贝到容器层

    3. 修改文件的拷贝同时底层的文件对于容器层是不可见的.

      只说了修改和读取那么当容器层要删除一个镜像层的文件时会发生什么呢让我们看看。

      先直接在底层镜像层中创建一个文件还记得上文中说到的那个只有diff目录和link文件的目录吗?那个就是最底层的镜像层

我们直接在diff/tmp/目录中创建一个文件文件名为thisIsAFileCreateImageLayer

      然后运行一个容器进入tmp目录可以看到这个文件对于容器是可见的.

     在容器层删除该文件

 

     在镜像层看看

 

       由上图可以看到在镜像层该文件是依然存在的这是因为在容器层在容器层删除文件或者目录

, overlayfs采用了whiteoutsopaque技术.

      Whiteouts是一个设备号为0/0的字符设备文件当上层目录中发现一个whiteout文件时在上层目录中读取底层的同名的文件时底层的文件就会被忽略.

如下图所示在新创建的容器层中我们可以看到一个设备号为0,0的字符设备文件.

 

接下来我来尝试解答一下我之前的疑问:

其实前两个问题已经得到了解答, 先说说第三个问题

3. 不同版本的ubuntu镜像有什么区别比如说 ubuntu:18.04ubuntn:16.04  的区别?

     不同版本的ubuntu的区别我目前知道的区别是软件库的版本不同. 

4. Docker镜像为什么要分层每层都包含什么什么时候会创建新的一层 ? 每层的权限是如何配置的只有最底层的镜像层是只读的吗?
     分层实现了空间最小化的隔离, 在运行一个新的容器时会创建一个新的读写层, 在使用Dockerfile构建新的镜像时会在已有的镜像层的基础上创建新的一层.
 

参考

https://docs.docker.com/storage/storagedriver/   //关于docker存储驱动很好的讲解
 
posted @ 2018-08-20 14:24  成蹊0xc000  阅读(262)  评论(2编辑  收藏  举报