本章節是對上章節Docker鏡像原理理解的鞏固,從Linux系統運行基礎到OverlayFS存儲機制 去了解與分析;在底層,鏡像是怎樣實現存儲的;並且會詳細說明存儲文件的作用。
一、Linux 系統運行基礎
Linux 系統正常運行, 通常需要兩個文件系統:
1、boot file system (bootfs)
1、 包含 Boot Loader與Kernel文件,用戶不能修改這些文件。並且在系統啟動過程完成之后, 整個系統的內核都會被加載進內存。此時bootfs會被卸載, 從而釋放出所占用的系統內存。
2、在容器中可以運行不同版本的Linux, 說明對於同樣內核版本的不同的 Linux 發行版的 bootfs 都是一致的, 否則會無法啟動。因此可以推斷, Docker運行是需要內核支持 的。
3、Linux系統中典型的bootfs目錄: (核心) /boot/vmlinuz、(核心解壓縮所需 RAM Disk) /boot/initramfs
2、root file system (rootfs)
1、不同的Linux發行版本, bootfs相同, rootfs不同(二進制文件)。
2、每個容器有自己的 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 (讀寫)
upperdir 則是在 lowerdir 之上的一層, 為讀寫層。容器在啟動的時候會創建, 所有對容 器的修改, 都是在這層。比如容器啟動寫入的日志文件,或者是應用程序寫入的臨時 文件。
3、MergedDir (展示)
merged 目錄是容器的掛載點,在用戶視角能夠看到的所有文件,都是從這層展示的。
LowerDir、Upperdir、MergedDir 關系圖:
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、運行中容器的存儲結構
1、前台啟動,直接進入到容器
[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
2、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
2、init層主要內容是什么?
init層是以一個uuid+-init結尾表示,放在只讀層(Lower)和讀寫層(upperdir)之間,
作用只是存放/etc/hosts、/etc/resolv.conf 等文件。
3、為什么需要init層?
1、容器在啟動以后, 默認情況下lower層是不能夠修改內容的, 但是用戶有需求需要修改主 機名與域名地址, 那么就需要添加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、鏡像所掛載的目錄層為 Lower 層,然后通過 Merged 展示所有的文件目錄與文件。用戶寫入的所有文件都是在 UpperDir 目錄,並且會在 UpperDir 建立於 Merged 層展示的文件 目錄結構, 所以用戶就可以看到寫入的文件。並且底層的鏡像是不能被修改(如果掛載目 錄為 UpperDir,則可以修改源鏡像)。
-
2、在下次重新啟動已經停止的容器的時候, 如果容器的 ID 沒有發生改變,那么所寫入的文 件是存在物理系統中的; 反之就會是一個新的容器,之前手工創建的文件是不存在的。
3、基於容器創建的鏡像,就相當於容器的快照, 可以刪除原來的容器, 但是不能刪除原來 的鏡像
4、基於鏡像創建的鏡像,原來的鏡像就是新鏡像的 low 層 (build), tag 則是沒有區別
5、容器啟動以后,鏡像就存在於容器的low 層,所有的寫入都是在upper