Docker 魔法解密:探索 UnionFS 与 OverlayFS
本文主要介紹了 Docker 的另一個核心技術:Union File System。主要包括對 overlayfs 的演示,以及分析 docker 是如何借助 ufs 實現容器 rootfs 的。
如果你對云原生技術充滿好奇,想要深入了解更多相關的文章和資訊,歡迎關注微信公眾號。
搜索公眾號【探索云原生】即可訂閱
1. 概述
Union File System
Union File System ,簡稱 UnionFS 是一種為 Linux FreeBSD NetBSD 操作系統設計的,把其他文件系統聯合到一個聯合掛載點的文件系統服務。
它使用 branch 不同文件系統的文件和目錄“透明地”覆蓋,形成一個單一一致的文件系統。
這些 branches 或者是 read-only 或者是 read-write 的,所以當對這個虛擬后的聯合文件系統進行寫操作的時候,系統是真正寫到了一個新的文件中。看起來這個虛擬后的聯合文件系統是可以對任何文件進行操作的,但是其實它并沒有改變原來的文件,這是因為 unionfs 用到了一個重要的資管管理技術叫寫時復制。
寫時復制(copy-on-write,下文簡稱 CoW),也叫隱式共享,是一種對可修改資源實現高效復制的資源管理技術。
它的思想是,如果一個資源是重復的,但沒有任何修改,這時候并不需要立即創建一個新的資源,這個資源可以被新舊實例共享。
創建新資源發生在第一次寫操作,也就是對資源進行修改的時候。通過這種資源共享的方式,可以顯著地減少未修改資源復制帶來的消耗,但是也會在進行資源修改的時候增減小部分的開銷。
UnionFS,最主要的功能是將多個不同位置的目錄聯合掛載(union mount)到同一個目錄下。
比如,我現在有兩個目錄 A 和 B,它們分別有兩個文件:
$ tree
.
├── A
│ ├── a
│ └── x
└── B
├── b
└── x
然后,我使用聯合掛載的方式,將這兩個目錄掛載到一個公共的目錄 C 上:
$ mkdir C
$ mount -t aufs -o dirs=./A:./B none ./C
這時,我再查看目錄 C 的內容,就能看到目錄 A 和 B 下的文件被合并到了一起:
$ tree ./C
./C
├── a
├── b
└── x
可以看到,在這個合并后的目錄 C 里,有 a、b、x 三個文件,并且 x 文件只有一份。這,就是“合并”的含義。
這就是聯合文件系統,目的就是將多個文件聯合在一起成為一個統一的視圖。
常見實現
AUFS
AuFS 的全稱是 Another UnionFS,后改名為 Alternative UnionFS,再后來干脆改名叫作 Advance UnionFS。
AUFS 完全重寫了早期的 UnionFS 1.x,其主要目的是為了可靠性和性能,并且引入了一些新的功能,比如可寫分支的負載均衡。
AUFS 的一些實現已經被納入 UnionFS 2.x 版本。
AUFS 只是 Docker 使用的存儲驅動的一種,除了 AUFS 之外,Docker 還支持了不同的存儲驅動,包括 aufs、devicemapper、overlay2、zfs 和 vfs 等等,在最新的 Docker 中,overlay2 取代了 aufs 成為了推薦的存儲驅動,但是在沒有 overlay2 驅動的機器上仍然會使用 aufs 作為 Docker 的默認驅動。
overlayfs
Overlayfs 是一種類似 aufs 的一種堆疊文件系統,于 2014 年正式合入 Linux-3.18 主線內核,目前其功能已經基本穩定(雖然還存在一些特性尚未實現)且被逐漸推廣,特別在容器技術中更是勢頭難擋。
Overlayfs 是一種堆疊文件系統,它依賴并建立在其它的文件系統之上(例如 ext4fs 和 xfs 等等),并不直接參與磁盤空間結構的劃分,僅僅將原來底層文件系統中不同的目錄進行“合并”,然后向用戶呈現。
簡單的總結為以下 3 點:
- 1)上下層同名目錄合并;
- 2)上下層同名文件覆蓋;
- 3)lower dir 文件寫時拷貝。
這三點對用戶都是不感知的。
假設我們有 dir1 和 dir2 兩個目錄:
dir1 dir2
/ /
a a
b c
然后我們可以把 dir1 和 dir2 掛載到 dir3 上,就像這樣:
dir3
/
a
b
c
需要注意的是:在 overlay 中 dir1 和 dir2 是有上下關系的。lower 和 upper 目錄不是完全一致,有一些區別,具體見下一節。
2. overlayfs 演示
當前 overlayfs 比較主流,因此使用 overlayfs 進行演示。
環境準備
具體演示如下:
創建一個如下結構的目錄:
.
├── lower
│ ├── a
│ └── c
├── merged
├── upper
│ ├── a
│ └── b
└── work
具體命令如下:
mkdir ./{merged,work,upper,lower}
touch ./upper/{a,b}
touch ./lower/{a,c}
然后進行 mount 操作:
# -t overlay 表示文件系統為 overlay
# -o lowerdir=./lower,upperdir=./upper,workdir=./work 指定 lowerdir、upperdir以及 workdir這3個目錄。
# 其中 lowerdir 是自讀的,upperdir是可讀寫的,
sudo mount \
-t overlay \
overlay \
-o lowerdir=./lower,upperdir=./upper,workdir=./work \
./merged
此時目錄結構如下:
.
├── lower
│ ├── a
│ └── c
├── merged
│ ├── a
│ ├── b
│ └── c
├── upper
│ ├── a
│ └── b
└── work
└── work
可以看到,merged 目錄已經可以同時看到 lower 和 upper 中的文件了,而由于文件 a 同時存在于 lower 和 upper 中,因此 lower 中的被覆蓋了,只顯示了一個 a。
修改文件
雖然 lower 和 upper 中的文件都出現在了 merged 目錄,但是二者還是有區別的。
lower 為底層目錄,只提供數據,不能寫。
upper 為上層目錄,是可讀寫的。
測試:
# 分別對 merged 中的文件b和c寫入數據
# 其中文件 c 來自 lower,b來自 upper
echo "will-persist" > ./merged/b
echo "wont-persist" > ./merged/c
修改后從 merged 這個視圖進行查看:
$ cat ./merged/b
will-persist
$ cat ./merged/c
wont-persist
可以發現,好像兩個文件都被更新了,難道上面的結論是錯的?
再從 upper 和 lower 視角進行查看:
$ cat ./upper/b
will-persist
$ cat ./lower/c
(empty)
可以發現 lower 中的文件 c 確實沒有被改變。
那么 merged 中查看的時候,文件 c 為什么有數據呢?
由于 lower 是不可寫的,因此采用了 CoW 技術,在對 c 進行修改時,復制了一份數據到 overlay 的 upper dir,即這里的 upper 目錄,進入 upper 目錄查看是否存在 c 文件:
[root@iZ2zefmrr626i66omb40ryZ upper]$ ll
total 8
-rw-r--r-- 1 root root 0 Jan 18 18:50 a
-rw-r--r-- 1 root root 13 Jan 18 19:10 b
-rw-r--r-- 1 root root 13 Jan 18 19:10 c
[root@iZ2zefmrr626i66omb40ryZ upper]$ cat c
wont-persist
可以看到,upper 目錄中確實存在了 c 文件,
因為是從 lower copy 到 upper,因此也叫做 copy_up。
刪除文件
首先往 lower 目錄中寫入一個文件 f
[root@iZ2zefmrr626i66omb40ryZ ufs]$ cd lower/
[root@iZ2zefmrr626i66omb40ryZ lower]$ echo fff >> f
然后到 merge 目錄查看,能否看到文件 f
[root@iZ2zefmrr626i66omb40ryZ lower]$ ls ../merged/
f
果然 lower 中添加后,merged 中也能直接看到了。
然后再 merged 中去刪除文件 f:
[root@iZ2zefmrr626i66omb40ryZ lower]$ cd ../merged/
[root@iZ2zefmrr626i66omb40ryZ merged]$ rm -rf f
# merged 中刪除后 lower 中文件還在
[root@iZ2zefmrr626i66omb40ryZ merged]$ ls ../lower/
a c e f
# 而 upper 中出現了一個大小為0的c類型文件f
[root@iZ2zefmrr626i66omb40ryZ merged]# ls -l ../upper/
total 0
c--------- 1 root root 0, 0 Jan 18 19:28 f
可以發現,overlay 中刪除 lower 中的文件,其實也是在 upper 中創建一個標記,表示這個文件已經被刪除了,而不會真正刪除 lower 中的文件。
測試一下:
[root@iZ2zefmrr626i66omb40ryZ merged]$ rm -rf ../upper/f
[root@iZ2zefmrr626i66omb40ryZ merged]$ ls
f
[root@iZ2zefmrr626i66omb40ryZ merged]$ cat f
fff
把 upper 中的大小為 0 的 f 文件給刪掉后,merged 中又可以看到 lower 中 f 了,而且內容也是一樣的。
說明 overlay 中的刪除其實是標記刪除。再 upper 中添加一個刪除標記,這樣該文件就被隱藏了,從 merged 中看到的效果就是文件被刪除了。
刪除文件或文件夾時,會在 upper 中添加一個同名的
c標識的文件,這個文件叫whiteout文件。當掃描到此文件時,會忽略此文件名。
添加文件
最后再試一下添加文件
# 首先在 merged 中創建文件 g
[root@iZ2zefmrr626i66omb40ryZ merged]$ echo ggg >> g
[root@iZ2zefmrr626i66omb40ryZ merged]$ ls
g
# 然后查看 upper,發現也存在文件 g
[root@iZ2zefmrr626i66omb40ryZ merged]$ ls ../upper/
g
# 在查看內容,發送是一樣的
[root@iZ2zefmrr626i66omb40ryZ merged]$ cat ../upper/g
ggg
說明 overlay 中添加文件其實就是在 upper 中添加文件。
測試一下刪除會怎么樣呢:
[root@iZ2zefmrr626i66omb40ryZ merged]$ rm -rf ../upper/g
[root@iZ2zefmrr626i66omb40ryZ merged]$ ls
f
把 upper 中的文件 g 刪除了,果然 merged 中的文件 g 也消失了。
3. docker 是如何使用 overlay 的?
上一節分析了 overlayfs 具體使用,這里分享一下 docker 是怎么使用 overlayfs。
大致流程
每一個 Docker image 都是由一系列的 read-only layers 組成:
- image layers 的內容都存儲在 Docker hosts filesystem 的 /var/lib/docker/aufs/diff 目錄下
- 而 /var/lib/docker/aufs/layers 目錄則存儲著 image layer 如何堆棧這些 layer 的 metadata。
docker 支持多種 graphDriver,包括 vfs、devicemapper、overlay、overlay2、aufs 等等,其中最常用的就是 aufs 了,但隨著 linux 內核 3.18 把 overlay 納入其中,overlay 的地位變得更重。
docker info命令可以查看 docker 的文件系統。
$ docker info
# ...
Storage Driver: overlay2
#...
比如這里用的就是 overlay2。
例如,假設我們有一個由兩層組成的容器鏡像:
layer1: layer2:
/etc /bin
myconf.ini my-binary
然后,在容器運行時將把這兩層作為 lower 目錄,創建一個空upper目錄,并將其掛載到某個地方:
sudo mount \
-t overlay \
overlay \
-o lowerdir=/layer1:/layer2,upperdir=/upper,workdir=/work \
/merged
最后將/merged用作容器的 rootfs。
這樣,容器中的文件系統就完成了。
具體分析
以構建鏡像方式演示以下 docker 是如何使用 overlayfs 的。
先拉一下 Ubuntu:20.04 的鏡像:
$ docker pull ubuntu:20.04
20.04: Pulling from library/ubuntu
Digest: sha256:626ffe58f6e7566e00254b638eb7e0f3b11d4da9675088f4781a50ae288f3322
Status: Downloaded newer image for ubuntu:20.04
docker.io/library/ubuntu:20.04
然后寫個簡單的 Dockerfile :
FROM ubuntu:20.04
RUN echo "Hello world" > /tmp/newfile
開始構建:
$ docker build -t hello-ubuntu .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM ubuntu:20.04
---> ba6acccedd29
Step 2/2 : RUN echo "Hello world" > /tmp/newfile
---> Running in ee79bb9802d0
Removing intermediate container ee79bb9802d0
---> 290d8cc1f75a
Successfully built 290d8cc1f75a
Successfully tagged hello-ubuntu:latest
查看構建好的鏡像:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-ubuntu latest 290d8cc1f75a 13 minutes ago 72.8MB
ubuntu 20.04 ba6acccedd29 3 months ago 72.8MB
使用docker history命令,查看鏡像使用的 image layer 情況:
$ docker history hello-ubuntu
IMAGE CREATED CREATED BY SIZE COMMENT
290d8cc1f75a 22 seconds ago /bin/sh -c echo "Hello world" > /tmp/newfile 12B
ba6acccedd29 3 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 3 months ago /bin/sh -c #(nop) ADD file:5d68d27cc15a80653… 72.8MB
帶 missing 標記的 layer 是自 Docker 1.10 之后,一個鏡像的 image layer image history 數據都存儲在 個文件中導致的,這是 Docker 官方認為的正常行為。
可以看到,290d8cc1f75a 這一層在最上面,只用了 12Bytes,而下面的兩層都是共享的,這也證明了 AUFS 是如何高效使用磁盤空間的。
然后去找一下具體的文件:
docker 默認的存儲目錄是/var/lib/docker,具體如下:
[root@iZ2zefmrr626i66omb40ryZ docker]$ ls -al
total 24
drwx--x--x 13 root root 167 Jul 16 2021 .
drwxr-xr-x. 42 root root 4096 Oct 13 15:07 ..
drwx--x--x 4 root root 120 May 24 2021 buildkit
drwx-----x 7 root root 4096 Jan 17 20:25 containers
drwx------ 3 root root 22 May 24 2021 image
drwxr-x--- 3 root root 19 May 24 2021 network
drwx-----x 53 root root 12288 Jan 17 20:25 overlay2
drwx------ 4 root root 32 May 24 2021 plugins
drwx------ 2 root root 6 Jul 16 2021 runtimes
drwx------ 2 root root 6 May 24 2021 swarm
drwx------ 2 root root 6 Jan 17 20:25 tmp
drwx------ 2 root root 6 May 24 2021 trust
drwx-----x 5 root root 266 Dec 29 14:31 volumes
在這里,我們只關心image和overlay2就足夠了。
- image:鏡像相關
- overlay2:docker 文件所在目錄,也可能不叫這個名字,具體和文件系統有關,比如可能是 aufs 等。
先看 image目錄:
docker 會在/var/lib/docker/image目錄下按每個存儲驅動的名字創建一個目錄,如這里的overlay2。
[root@iZ2zefmrr626i66omb40ryZ docker]$ cd image/
[root@iZ2zefmrr626i66omb40ryZ image]$ ls
overlay2
# 看下里面有哪些文件
[root@iZ2zefmrr626i66omb40ryZ image]$ tree -L 2 overlay2/
overlay2/
├── distribution
│ ├── diffid-by-digest
│ └── v2metadata-by-diffid
├── imagedb
│ ├── content
│ └── metadata
├── layerdb
│ ├── mounts
│ ├── sha256
│ └── tmp
└── repositories.json
這里的關鍵地方是imagedb和layerdb目錄,看這個目錄名字,很明顯就是專門用來存儲元數據的地方。
- layerdb:docker image layer 信息
- imagedb:docker image 信息
因為 docker image 是由 layer 組成的,而 layer 也已復用,所以分成了 layerdb 和 imagedb。
先去 imagedb 看下剛才構建的鏡像:
$ cd overlay2/imagedb/content/sha256
$ ls
[root@iZ2zefmrr626i66omb40ryZ sha256]# ls
0c7ea9afc0b18a08b8d6a660e089da618541f9aa81ac760bd905bb802b05d8d5 61ad638751093d94c7878b17eee862348aa9fc5b705419b805f506d51b9882e7
// .... 省略
b20b605ed599feb3c4757d716a27b6d3c689637430e18d823391e56aa61ecf01
60d84e80b842651a56cd4187669dc1efb5b1fe86b90f69ed24b52c37ba110aba ba6acccedd2923aee4c2acc6a23780b14ed4b8a5fa4e14e252a23b846df9b6c1
可以看到,都是 64 位的 ID,這些就是具體鏡像信息,剛才構建的鏡像 ID 為290d8cc1f75a,所以就找290d8cc1f75a開頭的文件:
[root@iZ2zefmrr626i66omb40ryZ sha256]$ cat 290d8cc1f75a4e230d645bf03c49bbb826f17d1025ec91a1eb115012b32d1ff8
{"architecture":"amd64","config":{"Hostname":"","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["bash"],"Image":"sha256:ba6acccedd2923aee4c2acc6a23780b14ed4b8a5fa4e14e252a23b846df9b6c1","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"container":"ee79bb9802d0ff311de6d606fad35fa7e9ab0c1cb4113837a50571e79c9454df","container_config":{"Hostname":"","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh","-c","echo \"Hello world\" \u003e /tmp/newfile"],"Image":"sha256:ba6acccedd2923aee4c2acc6a23780b14ed4b8a5fa4e14e252a23b846df9b6c1","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"created":"2022-01-17T12:25:14.91890037Z","docker_version":"20.10.6","history":[{"created":"2021-10-16T00:37:47.226745473Z","created_by":"/bin/sh -c #(nop) ADD file:5d68d27cc15a80653c93d3a0b262a28112d47a46326ff5fc2dfbf7fa3b9a0ce8 in / "},{"created":"2021-10-16T00:37:47.578710012Z","created_by":"/bin/sh -c #(nop) CMD [\"bash\"]","empty_layer":true},{"created":"2022-01-17T12:25:14.91890037Z","created_by":"/bin/sh -c echo \"Hello world\" \u003e /tmp/newfile"}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:9f54eef412758095c8079ac465d494a2872e02e90bf1fb5f12a1641c0d1bb78b","sha256:b3cce2ce0405ffbb4971b872588c5b7fc840514b807f18047bf7d486af79884c"]}}
這就是 image 的 metadata,這里主要關注 rootfs:
# 和 docker inspect 命令顯示的內容差不多
// ...
"rootfs":{"type":"layers","diff_ids":
[
"sha256:9f54eef412758095c8079ac465d494a2872e02e90bf1fb5f12a1641c0d1bb78b",
"sha256:b3cce2ce0405ffbb4971b872588c5b7fc840514b807f18047bf7d486af79884c"
]
}
// ...
可以看到 rootfs 的 diff_ids 是一個包含了兩個元素的數組,這兩個元素就是組成 hello-ubuntu 鏡像的兩個 Layer 的diffID。
從上往下看,就是底層到頂層,即9f54eef412...是 image 的最底層。
然后根據 layerID 去layerdb目錄尋找對應的 layer:
[root@iZ2zefmrr626i66omb40ryZ overlay2]# tree -L 2 layerdb/
layerdb/
├── mounts
├── sha256
└── tmp
在這里我們只管mounts和sha256兩個目錄,先打印以下 sha256 目錄
$ cd /var/lib/docker/image/overlay2/layerdb/sha256/
$ ls
05dd34c0b83038031c0beac0b55e00f369c2d6c67aed11ad1aadf7fe91fbecda
// ... 省略
6aa07175d1ac03e27c9dd42373c224e617897a83673aa03a2dd5fb4fd58d589f
可以看到,layer 里也是 64 位隨機 ID 構成的目錄,找到剛才 hello-ubuntu 鏡像的最底層 layer:
$ cd 9f54eef412758095c8079ac465d494a2872e02e90bf1fb5f12a1641c0d1bb78b
[root@iZ2zefmrr626i66omb40ryZ 9f54eef412758095c8079ac465d494a2872e02e90bf1fb5f12a1641c0d1bb78b]$ ls
cache-id diff size tar-split.json.gz
文件含義如下:
- cache-id:為具體
/var/lib/docker/overlay2/<cache-id>存儲路徑 - diff:diffID,用于計算 ChainID
- size:當前 layer 的大小
docker 使用了 chainID 的方式來保存 layer,layer.ChainID 只用本地,根據 layer.DiffID 計算,并用于 layerdb 的目錄名稱。
chainID 唯一標識了一組(像糖葫蘆一樣的串的底層)diffID 的 hash 值,包含了這一層和它的父層(底層),
- 當然這個糖葫蘆可以有一顆山楂,也就是 chainID(layer0)==diffID(layer0);
- 對于多顆山楂的糖葫蘆,ChainID(layerN) = SHA256hex(ChainID(layerN-1) + " " + DiffID(layerN))。
# 查看 diffID,
$ cat diff
sha256:9f54eef412758095c8079ac465d494a2872e02e90bf1fb5f12a1641c0d1bb78b
由于這是 layer0,所以 chainID 就是 diffID,然后開始計算 layer1 的 chainID:
ChainID(layer1) = SHA256hex(ChainID(layer0) + " " + DiffID(layer1))
layer0 的 chainID 是9f54...,而 layer1 的 diffID 根據 rootfs 中的數組可知,為b3cce...
計算 ChainID:
$ echo -n "sha256:9f54eef412758095c8079ac465d494a2872e02e90bf1fb5f12a1641c0d1bb78b sha256:b3cce2ce0405ffbb4971b872588c5b7fc840514b807f18047bf7d486af79884c" | sha256sum| awk '{print $1}'
6613b10b697b0a267c9573ee23e54c0373ccf72e7991cf4479bd0b66609a631c
一定注意要加上 “sha256:”和中間的空格“ ” 這兩部分。
因此 layer1 的 chainID 就是6613...
找到 layerdb 里面以sha256+6613 開頭的目錄
$ cd /var/lib/docker/image/overlay2/layerdb/sha2566613b10b697b0a267c9573ee23e54c0373ccf72e7991cf4479bd0b66609a631c
# 根據這個大小可以知道,就是hello-ubuntu 鏡像的最上面層 layer
[root@iZ2zefmrr626i66omb40ryZ 6613b10b697b0a267c9573ee23e54c0373ccf72e7991cf4479bd0b66609a631c]$ cat size
12
# 查看 cache-id 找到 文件系統中的具體位置
[root@iZ2zefmrr626i66omb40ryZ 6613b10b697b0a267c9573ee23e54c0373ccf72e7991cf4479bd0b66609a631c]$ cat cache-id
83b569c0f5de093192944931e4f41dafb2d7f80eae97e4bd62425c20e2079f65
根據 cache-id 進入具體數據存儲目錄:
格式為
/var/lib/docker/overlay2/<cache-id>
# 進入剛才生成的目錄
$ cd /var/lib/docker/overlay2/83b569c0f5de093192944931e4f41dafb2d7f80eae97e4bd62425c20e2079f65
[root@iZ2zefmrr626i66omb40ryZ 83b569c0f5de093192944931e4f41dafb2d7f80eae97e4bd62425c20e2079f65]# ls -al
total 24
drwx-----x 4 root root 55 Jan 17 20:25 .
drwx-----x 53 root root 12288 Jan 17 20:25 ..
drwxr-xr-x 3 root root 17 Jan 17 20:25 diff
-rw-r--r-- 1 root root 26 Jan 17 20:25 link
-rw-r--r-- 1 root root 28 Jan 17 20:25 lower
drwx------ 2 root root 6 Jan 17 20:25 work
# 查看 diff 目錄
[root@iZ2zefmrr626i66omb40ryZ
83b569c0f5de093192944931e4f41dafb2d7f80eae97e4bd62425c20e2079f65]$ cd diff/
[root@iZ2zefmrr626i66omb40ryZ diff]$ ls
tmp
[root@iZ2zefmrr626i66omb40ryZ diff]$ cd tmp/
[root@iZ2zefmrr626i66omb40ryZ tmp]$ ls
newfile
[root@iZ2zefmrr626i66omb40ryZ tmp]# cat newfile
Hello world
可以看到,我們新增的 newfile 就在這里。
如果你對云原生技術充滿好奇,想要深入了解更多相關的文章和資訊,歡迎關注微信公眾號。
搜索公眾號【探索云原生】即可訂閱
4. 參考
a practical look into overlayfs
overlayfs.txt
docker-overlay2 文件系統
總結
以上是生活随笔為你收集整理的Docker 魔法解密:探索 UnionFS 与 OverlayFS的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: K8s 网关选型血泪史
- 下一篇: 5分钟教会你如何在生产环境debug代码