聯合掛載(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.txt,upper/會多出一個 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 時行為奇怪)時就不會慌張。
延伸閱讀#
- Linux kernel 文件:Overlay Filesystem ↗
- Docker 官方文件:Use the OverlayFS storage driver ↗