同样是用 overlay 联合文件系统 实现容器路径 和 宿主机路径的映射。
image.png

测试挂载效果

我们把/root/tmp/abc作为映射到宿主机的目录,并且作为upperdir上层读写层。把容器中的merged目录作为lower只读层,形成宗卷映射,最后重新把merged目录作为挂载点,重新挂载回了merged目录。

1. 首先挂载

  1. root@debian:~/tmp/overlay# mount -t overlay overlay -o lowerdir=./merged,upperdir=/root/tmp/abc,workdir=./work ./merged

2. 实验一

测试容器内目录创建文件,宿主机目录变化。在merged目录,即容器中创建一个merged.txt。可以看到/root/tmp/abc作为读写层也看到了新创建的文件。

  1. root@debian:~/tmp/overlay# ls merged/
  2. abc.txt
  3. root@debian:~/tmp/overlay# touch merged/merged.txt
  4. root@debian:~/tmp/overlay# cd ..
  5. root@debian:~/tmp# tree
  6. .
  7. |-- abc
  8. | |-- abc.txt
  9. | `-- merged.txt
  10. `-- overlay
  11. |-- lower
  12. | |-- ld
  13. | | `-- ld.txt
  14. | `-- ld1.txt
  15. |-- merged
  16. | |-- abc.txt
  17. | `-- merged.txt
  18. |-- upper
  19. | |-- ld1.txt
  20. | |-- ud
  21. | | `-- ud.txt
  22. | `-- ud2.txt
  23. `-- work
  24. `-- work
  25. 9 directories, 9 files

3. 实验二

测试宿主机目录创建文件,容器内目录变化。在root/tmp/abc目录,即宿主机中创建一个abcdddd.txt。可以看到容器中merged目录作为挂载点,也看到了新创建的文件。

  1. root@debian:~/tmp# touch abc/abcdddd.txt
  2. root@debian:~/tmp# tree
  3. .
  4. |-- abc
  5. | |-- abc.txt
  6. | |-- abcdddd.txt
  7. | `-- merged.txt
  8. `-- overlay
  9. |-- lower
  10. | |-- ld
  11. | | `-- ld.txt
  12. | `-- ld1.txt
  13. |-- merged
  14. | |-- abc.txt
  15. | |-- abcdddd.txt
  16. | `-- merged.txt
  17. |-- upper
  18. | |-- ld1.txt
  19. | |-- ud
  20. | | `-- ud.txt
  21. | `-- ud2.txt
  22. `-- work
  23. `-- work
  24. 9 directories, 11 files

3. 实验三

测试容器删除后的效果。umout取消挂载merged目录的挂载点,可以看到merged目录刚刚创建的文件都没了,不要慌张,我们可以在宿主机root/tmp/abc中的看到它们,这样就轻松实现了volume宗卷挂载。当再次重启容器的时候,只需要重新把宿主机的目录作为读写层,容器目录既作为只读层又作为挂载点就可以轻松恢复原状。

  1. root@debian:~/tmp/overlay# umount /root/tmp/overlay/merged
  2. root@debian:~/tmp/overlay# ls
  3. lower merged upper work
  4. root@debian:~/tmp/overlay# ls merged/
  5. root@debian:~/tmp/overlay# cd ..
  6. root@debian:~/tmp# tree
  7. .
  8. |-- abc
  9. | |-- abc.txt
  10. | |-- abcdddd.txt
  11. | `-- merged.txt
  12. `-- overlay
  13. |-- lower
  14. | |-- ld
  15. | | `-- ld.txt
  16. | `-- ld1.txt
  17. |-- merged
  18. |-- upper
  19. | |-- ld1.txt
  20. | |-- ud
  21. | | `-- ud.txt
  22. | `-- ud2.txt
  23. `-- work
  24. `-- work
  25. 9 directories, 8 files

挂载数据卷的过程

  1. 读取宿主机的文件目录,创建宿主机的文件目录(如果不存在的话),(/root/${parentURL}),作读写层
  2. 读取容器的挂载点目录,在容器文件系统中创建挂载点目录(/root/mnt/${containerURL}),作只读层
  3. 把宿主机文件目录 和 容器文件系统中的 挂载点目录 用overlay 挂载到容器的挂载点

运行容器效果

  1. 运行一个容器示例,在容器内container文件夹创建一个123.txt文件

image.png

  1. root@debian:~/GoWork/src/github.com/devhg/ddocker# go build .
  2. root@debian:~/GoWork/src/github.com/devhg/ddocker# ./ddocker run -it -v /root/volume:/container sh
  3. sh
  4. true
  5. {"level":"info","msg":"[/proc/self/exe init]","time":"2021-08-30T17:11:30+08:00"}
  6. {"level":"error","msg":"mkdir /root/busybox/ error: mkdir /root/busybox/: file exists","time":"2021-08-30T17:11:30+08:00"}
  7. {"level":"info","msg":"/sys/fs/cgroup/memory/ddocker-cgroup/tasks","time":"2021-08-30T17:11:30+08:00"}
  8. {"level":"info","msg":"init come on","time":"2021-08-30T17:11:30+08:00"}
  9. {"level":"info","msg":"command all is sh","time":"2021-08-30T17:11:30+08:00"}
  10. {"level":"info","msg":"current location is: /root/mnt","time":"2021-08-30T17:11:30+08:00"}
  11. {"level":"info","msg":"found path is /bin/sh","time":"2021-08-30T17:11:30+08:00"}
  12. {"level":"info","msg":"/bin/sh [sh]","time":"2021-08-30T17:11:30+08:00"}
  13. / # ls
  14. bin container dev etc home proc root sys tmp usr var
  15. / # cd container/
  16. /container # ls
  17. /container # pwd
  18. /container
  19. /container # touch 123.txt
  20. /container # ls
  21. 123.txt
  22. /container #
  1. 查看宿主机映射路径/root/volume情况,挂载数据卷成功

image.png

  1. 容器停止只有,宿主机路径文件仍然存在

image.png

  1. 重新运行容器,容器中复原宿主机的数据卷

image.png