Docker鏡像存儲

前言

之前的文章中有說過容器目錄的隔離機制. 今天來分析一下鏡像的文件系統.

Docker 已經用了很久了, 也知道鏡像存儲的時候是分層存儲的(從docker pull時分層下載就能看出), 但是具體是如何將多層進行聚合並生成最終展示的文件, 這個過程從未深究過. 既然不知道, 又難掩好奇, 就抽時間康康它具體是怎麼做的吧

OverlayFS

OverlayFS就是這樣一個聯合掛載的文件系統, 可以看看wiki上的介紹, 也可以看看內核文檔中的介紹.

它的作用簡單來說就是: 將多個目錄的文件內容融合爲一個目錄.

OverlayFS中, 文件目錄分爲四類:

  1. lowerdir: 只讀目錄, 可以有多個, 相同文件上層會覆蓋下層.
  2. upperdir: 讀寫層. 只有一個, 對文件的增刪改記錄在這裏
  3. mergedir: 在此目錄中展示合併後的文件內容
  4. workdir: 文件系統的臨時目錄, 在創建後被清空. 這一層是文件系統使用的, 具體作用在後面說明. (todo https://blog.csdn.net/luckyapple1028/article/details/78075358)

實戰

官方文檔中提到, 可以使用mount命令來掛載OverlayFS. 我們來測試一下

創建掛載相關的目錄及文件:

mkdir lower1 lower2 upper merged work
# lower文件被上層覆蓋
echo "lower1" > lower1/lower_change.txt 
echo "lower2" > lower2/lower_change.txt 
# lower文件在各層添加
echo "lower1" > lower1/lower1.txt 
echo "lower2" > lower2/lower2.txt 
# lower文件被upper覆蓋
echo "lower2" > lower2/upper.txt 
echo "upper" > upper/upper.txt 
# 文件掛載
mount -t overlay overlay -o lowerdir=lower1:lower2,upperdir=upper,workdir=work merged
# 卸載文件系統. 卸載後 merged 目錄下的所有文件均會消失
umount <dir>

image-20230604100836804

此時進入merged目錄查看文件, lower2中的同名文件會被lower1覆蓋. 現在, 讓我們來對系統進行簡單的測試, 以便於瞭解其原理(對merged目錄操作):

  1. 創建文件: 創建的文件會同步出現在upperdir目錄下
  2. 修改文件: 修改的文件, 會將修改後的文件在upperdir下寫一份
  3. 刪除文件: 刪除文件就比較有意思了, 將lower1.txt文件刪除後, 會在upperdir下創建一個whiteout文件來標識下層文件被刪除. 如下圖:

image-20230604101625571

當我們對掛載文件做了一系列操作之後, 可以嘗試下這樣的操作:

mkdir upper_new
umount merged
mount -t overlay overlay -o lowerdir=upper:lower1:lower2,upperdir=upper_new,workdir=work merged
# mount 命令可以看到當前所有的文件系統
mount 

這樣我們就將對文件系統的改動記錄下來了. 熟悉不熟悉? 這不就是docker save的操作麼.

workdir 作用

至此, 對OverlayFS系統也有一定了解了, 但是workdir我們從來就沒用到過, 它是做什麼的呢? 在官方文件中有說明, 我的理解是: 這個目錄是給文件系統使用的.

比如, 文件的刪除操作不是一步完成的, 涉及到文件刪除, upperdir創建覆蓋文件等操作, 爲了防止斷電等異常情況, 會接住workdir來實現原子刪除

不過具體的實現細節我沒有深究.

鏡像

好, 可以來看一下Docker的鏡像存儲了.

鏡像信息保存在/var/lib/docker/image/overlay2/imagedb/content/sha256/<image sha256>文件中. 其中rootfs字段記錄了鏡像的各層信息, 下方是nginx鏡像的信息. (或者用命令docker image inspect <image>查看也行)

{
		//...
    "rootfs":
    {
        "type": "layers",
        "diff_ids":
        [
            "sha256:8cbe4b54fa88d8fc0198ea0cc3a5432aea41573e6a0ee26eca8c79f9fbfa40e3",
            "sha256:4b8862fe7056d8a3c2c0910eb38ebb8fc08785eaa1f9f53b2043bf7ca8adbafb",
            "sha256:e60266289ce4a890aaf52b93228090998e28220aef04f128704141864992dd15",
            "sha256:7daac92f43be84ad9675f94875c1a00357b975d6c58b11d17104e0a0e04da370",
            "sha256:5e099cf3f3c83c449b8c062f944ac025c9bf2dd7ec255837c53430021f5a1517",
            "sha256:4fd83434130318dede62defafcc5853d03dae8636eccfa1b9dcd385d92e3ff19"
        ]
    }
}

layer信息則保存在/var/lib/docker/image/overlay2/layerdb/sha256/<layer sha256>目錄下, 此目錄下保存了以下幾個文件:

  • cache-id: 文件的索引. 當前層的具體數據保存在/var/lib/docker/overlay2/<cache-id>目錄下
  • diff: 就是上面的diff ids
  • size: 當前層大小

好, 現在我們可以到/var/lib/docker/overlay2/<cache-id>/diff目錄下看到這一層的具體數據了.

/var/lib/docker/overlay2/l目錄下保存了diff目錄的軟連接, 用於縮短路徑的吧, 給文件系統傳遞的就是這個路徑.

至此, 容器啓動後是如何做的心裏有數了吧. 將多個layer層作爲lowerdir, 新建一個upperdir來進行容器內的文件修改. 最終整合成完成的文件目錄. 再通過目錄掛載替換進程的文件系統.


當然了, 文件系統也不是隻有Overlay, 可以通過docker info命令查看當前使用的文件系統. 其他的比如: unionfs-fuse, mergerfs等等.

image-20230604110208409

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章