聯合掛載(Union Mount)的核心想法#

傳統 mount 是把一個檔案系統掛到一個目錄上;目錄原本的內容被遮蓋。聯合掛載(Union Mount)則是把多個目錄的內容「合併呈現」在同一個掛載點:

  • 多個來源目錄各自貢獻一部分檔案
  • 重複路徑時,依設定的優先級決定看到哪一份
  • 寫入有特定的目標層(通常是最上層),不會污染下層

OverlayFS 是 Linux kernel 內建的聯合檔案系統實作,從 3.18 開始進入主線,後續持續改進。它是 Docker 預設的 storage driver。

OverlayFS 的四個目錄#

OverlayFS 在 mount 時要指定四個概念性的目錄:

  • LowerDir:底層 read-only 來源(可以是多個,用冒號串接)
  • UpperDir:上層 read-write 來源
  • MergedDir:使用者實際看到的合併視圖(mount point)
  • WorkDir:OverlayFS 內部使用的工作目錄,必須與 UpperDir 在同一個檔案系統

WorkDir 不是給使用者看的;它是 OverlayFS 在做 atomic rename、whiteout 等操作時的暫存空間。權限與位置受 kernel 嚴格規範。

mount -t overlay 動手做#

不需要 Docker 也可以玩 OverlayFS。準備四個空目錄就能掛:

mkdir -p /tmp/ovl/{lower,upper,work,merged}
echo "from lower" > /tmp/ovl/lower/a.txt

sudo mount -t overlay overlay \
  -o lowerdir=/tmp/ovl/lower,upperdir=/tmp/ovl/upper,workdir=/tmp/ovl/work \
  /tmp/ovl/merged

ls /tmp/ovl/merged
cat /tmp/ovl/merged/a.txt

預期觀察:

  • merged/a.txt 顯示 from lower,雖然檔案實際存在 lower/
  • merged/ 中新增檔案 b.txt,會出現在 upper/,但 lower/ 不變
  • 修改 merged/a.txt,OverlayFS 會把 lower/a.txt 拷貝一份到 upper/,往 upper/a.txt 寫;lower/a.txt 保持原狀
  • merged/ 中刪除 a.txtupper/ 會多出一個 whiteout(character device,major/minor 都是 0),lower/a.txt 也仍在原處

要卸載:

sudo umount /tmp/ovl/merged

這個小實驗把 Docker 看到的所有 layer 行為「不依賴 Docker」重現了一次。

多層 LowerDir#

OverlayFS 支援多個 LowerDir,這正是 Docker 多 layer 的基礎:

sudo mount -t overlay overlay \
  -o lowerdir=/tmp/ovl/l3:/tmp/ovl/l2:/tmp/ovl/l1,upperdir=/tmp/ovl/upper,workdir=/tmp/ovl/work \
  /tmp/ovl/merged

規則:

  • lowerdir 用冒號串接,左邊優先級高(接近 upper)
  • 同一路徑的檔案以最上面那層為準
  • 所有 lower 都是 read-only,OverlayFS 不會寫到它們
  • upper 是唯一可寫的層

對應到 Docker:image 的所有 layer 依序排成 LowerDir,container 的可寫層是 UpperDir。

Storage Driver 的演進#

Docker 在不同 Linux 環境支援過多種聯合檔案系統,主要的脈絡:

  • aufs:早期 Docker 的預設,功能完整但長年沒能進入 Linux 主線 kernel;只在打了補丁的發行版(如 Ubuntu)能用
  • overlay:第一代主線 OverlayFS 驅動。簡單、能用,但每層只能有一個 lower,多層需要層層 mount,效能與相容性有限
  • overlay2:第二代驅動,原生支援多 LowerDir,效能與穩定性大幅提升;現在 Linux 上 Docker 的預設
  • 其他歷史驅動:devicemapper、btrfs、zfs、vfs,用於特殊環境(例如老舊 kernel、特定檔案系統)

現代 Linux 上若沒有特殊原因,使用 overlay2 即可。可以用 docker info | grep -i storage 確認當前的 driver。

OverlayFS 的限制#

OverlayFS 不是完美的:

  • 不是 POSIX 完全相容;某些跨層 rename 行為與一般檔案系統不同
  • 對 inode 的計數方式特殊,某些工具看到的 inode 數會異常
  • 不適合作為「需要強一致性的共享儲存」;它的設計目標是 container 的隔離,不是分散式

知道這些限制,遇到怪現象(例如 mv 在跨 lower/upper 時行為奇怪)時就不會慌張。

延伸閱讀#