本章节是对上章节Docker镜像原理理解的巩固,从Linux系统运行基础到OverlayFS存储机制 去了解与分析;在底层,镜像是怎样实现存储的;并且会详细说明存储文件的作用。

一、Linux 系统运行基础
Linux 系统正常运行, 通常需要两个文件系统:

bootfs)
  1、 包含 Boot Loader与Kernel文件,用户不能修改这些文件。并且在系统启动过程完成之后, 整个系统的内核都会被加载进内存。此时bootfs会被卸载, 从而释放出所占用的系统内存。

Docker运行是需要内核支持 的。

  3、Linux系统中典型的bootfs目录: (核心) /boot/vmlinuz、(核心解压缩所需 RAM Disk) /boot/initramfs

rootfs)
  1、不同的Linux发行版本, bootfs相同, rootfs不同(二进制文件)。

rootfs, 它来自不同的 Linux 发行版的基础镜像,包括 Ubuntu, Debian 和 SUSE 等。

  3、使用不同的rootfs 就决定了, 在构建镜像的过程中, 可以使用哪些系统的命令。 4) 典型的rootfs 目录: /dev、/proc、/bin、/etc、 /lib、/usr

2、OverlayFS 存储原理

    OverlayFS 结构分为三个层: LowerDir、Upperdir、MergedDir

    1、LowerDir (只读)

  只读的 image layer,其实就是 rootfs, 在使用 Dockfile 构建镜像的时候, Image Layer

  可以分很多层,所以对应的 lowerdir 会很多(源镜像)。

    2、Upperdir (读写)

比如容器启动写入的日志文件,或者是应用程序写入的临时 文件。

    3、MergedDir (展示)
  merged 目录是容器的挂载点,在用户视角能够看到的所有文件,都是从这层展示的。

、Upperdir、MergedDir 关系图:

docker ram docker ramfs_docker ram

3、分析镜像存储结构

    1、获取镜像存储路径

  通过镜像信息获取到物理存储位置

[root@master jdk]# docker image inspect jre8:1.0        
.......
        "GraphDriver": {
            "Data": {
                "LowerDir": "/data/docker/overlay2/0dabd34b699bd07a6fedc787305c029837a509ba325dc19c913a83c1cdb42a3b/diff:/data/docker/overlay2/f0d9e8983ce0eb5189d1343a750ead40fff0b8bf2e7366a288746addca5e64f3/diff:/data/docker/overlay2/203eca2fa309cfded560ddbacaea64e1fe5644a74f8c682cdb94961b7f93f99a/diff:/data/docker/overlay2/cd72a119f6ac0b9796511e54070635c2f6250987163e851005079c310e020b80/diff:/data/docker/overlay2/7468ae5cef2f56d4db4a92d71b979bc2af007af9b5e4f6b3a635db1702a9d429/diff",
                "MergedDir": "/data/docker/overlay2/871f67b56f58f71f9774021c44b1ff35e7ef492dabb0dcf9a515353b085bf3f5/merged",
                "UpperDir": "/data/docker/overlay2/871f67b56f58f71f9774021c44b1ff35e7ef492dabb0dcf9a515353b085bf3f5/diff",
                "WorkDir": "/data/docker/overlay2/871f67b56f58f71f9774021c44b1ff35e7ef492dabb0dcf9a515353b085bf3f5/work"
            },
            "Name": "overlay2"
        },......

    2、分析Lower层

  LowerDir 层的存储是不允许创建文件, 此时的LowerDir实际上是其他的镜像的UpperDir层,也就是说在构建镜像的时候, 如果发现构建的内容相同, 那么不会重复的构建目录,而是使用其他镜像的Upper 层来作为本镜像的Lower

[root@master jdk]# touch  /data/docker/overlay2/0dabd34b699bd07a6fedc787305c029837a509ba325dc19c913a83c1cdb42a3b/diff/lower.txt

    3、分析Upper层

[root@master jdk]# touch  /data/docker/overlay2/871f67b56f58f71f9774021c44b1ff35e7ef492dabb0dcf9a515353b085bf3f5/diff/upper.txt

    4、分析Merged层

  属于对外展示层,只能在运行中的容器查看,镜像是查看不了的

4、运行中容器的存储结构

前台启动,直接进入到容器

[root@master lihanghang]# docker run -it jre8:1.0 bash  # 重新ssh 开个窗口
bash-4.3#

    2、查看容器挂在信息

  容器启动以后,挂载merged、lowerdir、upperdir以及workdir目录

  lowerdir是只读的image layer,其实就是rootfs

[root@master jdk]# docker ps
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS              PORTS                  NAMES
6816ade398c3        repo.abc.com/nginx:v1.0   "/docker-entrypoint.…"   4 hours ago         Up 4 hours          0.0.0.0:9091->80/tcp   condescending_shaw

 3、查看容器存储目录信息

#注意在所有的启动容器中会自动添加init目录, 此目录是存放系统的hostname与域名解析文件。

[root@master jdk]# docker inspect 6816ade398c3 
"Data": {
                "LowerDir": "/data/docker/overlay2/768c9e3cbf17b6dd61a47fa5ae935c5c7bc6adfc2a5c0ea79b38a9a3443ac929-init/diff:/data/docker/overlay2/696103a495dc761560c3ec0de8414619b559c483c5e6e66ec01fc2c5e6af12e1/diff:/data/docker/overlay2/b8e2bc89bb28f516fea555be11d33bf14334008be9c1e547e81088a54112510a/diff:/data/docker/overlay2/e2abf1e74fb5ee048de2066f1c2ee2e3750302cbbfbbd36bd9eff4d8872ec572/diff:/data/docker/overlay2/75c9819b8bf9e1de7b7471ee96632c3e20f82d1a88d5a58555a0b46f4ce952d8/diff:/data/docker/overlay2/0c809e2915134cf1ac493c5d5a814320923982d2384c1de0484d2c8bd5d9ad05/diff",
                "MergedDir": "/data/docker/overlay2/768c9e3cbf17b6dd61a47fa5ae935c5c7bc6adfc2a5c0ea79b38a9a3443ac929/merged",
                "UpperDir": "/data/docker/overlay2/768c9e3cbf17b6dd61a47fa5ae935c5c7bc6adfc2a5c0ea79b38a9a3443ac929/diff",
                "WorkDir": "/data/docker/overlay2/768c9e3cbf17b6dd61a47fa5ae935c5c7bc6adfc2a5c0ea79b38a9a3443ac929/work"
            },

5、容器文件存储解析

    1、容器运行时的UpperDir目录结构

# 本地窗口
[root@master jdk]# touch /data/docker/overlay2/d6e4e36c309de456d6025d56144feaf4097c9d133b7cda4a20baa8526ebe671a/diff/upper.txt
[root@master jdk]# echo 11111 > /data/docker/overlay2/d6e4e36c309de456d6025d56144feaf4097c9d133b7cda4a20baa8526ebe671a/diff/upper.txt
# 容器里面
bash-4.3# ls /
bin        etc        lib        media      opt        root       sbin       sys        upper.txt  var
dev        home       lib64      mnt        proc       run        srv        tmp        usr
bash-4.3# cat /upper.txt
11111

Work 目录

work目录用于联合挂载指定的工作目录,在overlay 把文件挂载到 upperdir后, work内容会

被清空,且在使用过程中(为空)其内容用户不可见。

    3、用户视角层Merged

#最后给用户展示的层,一般看到为一个完整的操作系统文件系统结构

[root@master jdk]# ll /data/docker/overlay2/d6e4e36c309de456d6025d56144feaf4097c9d133b7cda4a20baa8526ebe671a/merged
bin  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  upper.txt  usr  var

4、Lower 层

#Lower 包括两个层:a. 系统的init。b.容器的镜像层

Lower 记录父层的链接名称
[root@node-2 ~]# cat /var/lib/docker/overlay2/d4dc057329ecbf5a2f97293b6d49078e9cce6869a9f049ba5bc365f6fba424d2/lower
l/QCXVWDWYPFM5NRVMB2ZC2BE5WU:l/PUSOZBTJKJ2OBNKK2UQDNQLHCU
init 层 / 容器镜像层

    1、查看init层地址指向

  容器在启动的过程中, Lower 会自动挂载init的一些文件

[root@master jdk]# ls  /data/docker/overlay2/d6e4e36c309de456d6025d56144feaf4097c9d133b7cda4a20baa8526ebe671a-init/diff/etc
hostname  hosts  mtab  resolv.conf

init层主要内容是什么?

Lower)和读写层(upperdir)之间,

  作用只是存放/etc/hosts、/etc/resolv.conf 等文件。

    3、为什么需要init层?

主 机名与域名地址, 那么就需要添加init层中的文件(hostname, resolv.conf), 用于解决此类问 题.
  2、修改的内容只对当前的容器生效, 而在docker commit提交为镜像时候,并不会将init层提 交。

  3、init 文件存放的目录为/var/lib/docker/overlay2/<init_id>/diff

    4、查看init层文件

  hostname与resolv.conf 全部为空文件, 在系统启动以后由系统写入。注:不能在打镜像的时候copy进去,copy进去用这个镜像启动时,启动起来以后文件也是空的。

[root@master jdk]# ll  /data/docker/overlay2/d6e4e36c309de456d6025d56144feaf4097c9d133b7cda4a20baa8526ebe671a-init/diff/etc
总用量 0
-rwxr-xr-x. 1 root root  0 8月  24 00:03 hostname
-rwxr-xr-x. 1 root root  0 8月  24 00:03 hosts
lrwxrwxrwx. 1 root root 12 8月  24 00:03 mtab -> /proc/mounts
-rwxr-xr-x. 1 root root  0 8月  24 00:03 resolv.conf

总结

  1. 1、镜像所挂载的目录层为 Lower 层,然后通过 Merged 展示所有的文件目录与文件。用户写入的所有文件都是在 UpperDir 目录,并且会在 UpperDir 建立于 Merged 层展示的文件 目录结构, 所以用户就可以看到写入的文件。并且底层的镜像是不能被修改(如果挂载目 录为 UpperDir,则可以修改源镜像)。
  2. 2、在下次重新启动已经停止的容器的时候, 如果容器的 ID 没有发生改变,那么所写入的文 件是存在物理系统中的; 反之就会是一个新的容器,之前手工创建的文件是不存在的。

       3、基于容器创建的镜像,就相当于容器的快照, 可以删除原来的容器, 但是不能删除原来 的镜像

       4、基于镜像创建的镜像,原来的镜像就是新镜像的 low 层 (build), tag 则是没有区别

 

       5、容器启动以后,镜像就存在于容器的low 层,所有的写入都是在upper