概要

  • /root 目录为根目录主要存放 镜像等信息
  • /root/mnt/${containerID}/ 为容器挂载目录
  • /root/writePlayer/${containerID}/ 为容器 读写层目录
  • /root/${imageName}/ 为容器 只读层目录,也就是镜像解压后的目录
  • /root/work/ 为overlay所需要的一种目录

实现

https://github.com/devhg/ddocker/blob/main/container/init.go
https://github.com/devhg/ddocker/blob/main/container/volume.go

效果演示

文件系统和目录挂载

首先通过busybox镜像启动两个容器container1,container2,container1把宿主机/root/from1 挂载到容器/to1目录下。container2容器把宿主机/root/from2挂载到to2目录。
image.png

  1. ./ddocker run -d --name container1 -v /root/from1:/to1 busybox top
  2. ./ddocker run -d --name container2 -v /root/from2:/to2 busybox top

image.png
查看容器的目录信息。

另外打开一个新的terminal,查看宿主机/root目录下的内容,发现多了from1 from2两个挂载文件夹,mnt是所有容器文件系统的入口,writeLayer是所有容器读写层的总入口目录。上述的命令创建了两个容器,mnt/${containerID}/是整个容器的文件系统,writeLayer/${containerID}是整个容器的可读写层。
image.png

接下来,使用ddocker exec命令进入到container1容器中,并记录下下图的信息。
image.png

在另一个terminal中,查看宿主机writeLayer目录内容,多了两个容器的目录,分别是to1和to2。仔细观察我们也可以看到只有在to1-1目录发现了刚刚在容器中记录的内容,to1的内容却没有,这是因为to1的内容被映射到了from1中。

通过cat from1/test1.txt 看到了我们想看到的内容。所以映射的核心原理就是 把容器读写层作为只读层,宿主机目录作读写层后联合挂载到了mnt下。
image.png
to1/test1.txt 路径为新建的,映射到了宿主机,所以内容写到了容器的读写层 /writeLayer/${containerID}。
to1-1/test1.txt 路径为新建的,未映射到宿主机,所以内容写到了容器的读写层 /writeLayer/${containerID}。

相反,在宿主机映射目录from1/test1.txt 写入,
image.png
重新进入到容器当中,同样可以在容器中看到。
image.png

镜像打包

打包的原理就是tar -zcf

使用commit命令把container1打包成image1。可以看到在宿主机root目录下多个一个image1.tar,这个就是我们通过容器制作的镜像。
image.png

使用ddocker stop 和 ddocker rm 命令删除掉container1容器。可以看到container1在/root/writeLayer下的读写层被删掉了,而宿主机映射的/from1没有被删除掉。
image.png

使用如下命令创建container3,并重新复原的映射container1的目录内容。

  1. ./ddocker run -d --name container3 -v /root/from1:/to1 image1 top

使用 ddocker exec 命令进入container3,并写入下图内容。
image.png

进入另一个terminal,可以看到宿主机中看到了,container3新加的 “hello,container3”,并且重新创建了/root/writeLayer/${containerID[3] }
image.png