日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

修改文件

雖然 lower 和 upper 中的文件都出現(xiàn)在了 merged 目錄,但是二者還是有區(qū)別的。

lower 為底層目錄,只提供數(shù)據(jù),不能寫。

upper 為上層目錄,是可讀寫的。

測試:

# 分別對 merged 中的文件b和c寫入數(shù)據(jù)
# 其中文件 c 來自 lower,b來自 upper
echo "will-persist"  > ./merged/b
echo "wont-persist"  > ./merged/c

修改后從 merged 這個視圖進(jìn)行查看:

$ cat ./merged/b
will-persist
$ cat ./merged/c
wont-persist

可以發(fā)現(xiàn),好像兩個文件都被更新了,難道上面的結(jié)論是錯的?

再從 upper 和 lower 視角進(jìn)行查看:

$ cat ./upper/b
will-persist
$ cat ./lower/c
(empty)

可以發(fā)現(xiàn) lower 中的文件 c 確實(shí)沒有被改變。

那么 merged 中查看的時(shí)候,文件 c 為什么有數(shù)據(jù)呢?

由于 lower 是不可寫的,因此采用了 CoW 技術(shù),在對 c 進(jìn)行修改時(shí),復(fù)制了一份數(shù)據(jù)到 overlay 的 upper dir,即這里的 upper 目錄,進(jìn)入 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 目錄中確實(shí)存在了 c 文件,

因?yàn)槭菑?lower copy 到 upper,因此也叫做 copy_up。

Docker 魔法解密:探索 UnionFS 與 OverlayFS

刪除文件

首先往 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 中出現(xiàn)了一個大小為0的c類型文件f
[root@iZ2zefmrr626i66omb40ryZ merged]# ls -l ../upper/
total 0
c--------- 1 root root 0, 0 Jan 18 19:28 f

可以發(fā)現(xiàn),overlay 中刪除 lower 中的文件,其實(shí)也是在 upper 中創(chuàng)建一個標(biāo)記,表示這個文件已經(jīng)被刪除了,而不會真正刪除 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 了,而且內(nèi)容也是一樣的。

說明 overlay 中的刪除其實(shí)是標(biāo)記刪除。再 upper 中添加一個刪除標(biāo)記,這樣該文件就被隱藏了,從 merged 中看到的效果就是文件被刪除了。

刪除文件或文件夾時(shí),會在 upper 中添加一個同名的 c 標(biāo)識的文件,這個文件叫 whiteout 文件。

當(dāng)掃描到此文件時(shí),會忽略此文件名。

Docker 魔法解密:探索 UnionFS 與 OverlayFS

添加文件

最后再試一下添加文件

# 首先在 merged 中創(chuàng)建文件 g
[root@iZ2zefmrr626i66omb40ryZ merged]$ echo ggg >> g
[root@iZ2zefmrr626i66omb40ryZ merged]$ ls
g
# 然后查看 upper,發(fā)現(xiàn)也存在文件 g
[root@iZ2zefmrr626i66omb40ryZ merged]$ ls ../upper/
g
# 在查看內(nèi)容,發(fā)送是一樣的
[root@iZ2zefmrr626i66omb40ryZ merged]$ cat ../upper/g
ggg

說明 overlay 中添加文件其實(shí)就是在 upper 中添加文件。

測試一下刪除會怎么樣呢:

[root@iZ2zefmrr626i66omb40ryZ merged]$ rm -rf ../upper/g
[root@iZ2zefmrr626i66omb40ryZ merged]$ ls
f

把 upper 中的文件 g 刪除了,果然 merged 中的文件 g 也消失了。

Docker 魔法解密:探索 UnionFS 與 OverlayFS

3. docker 是如何使用 overlay 的?

上一節(jié)分析了 overlayfs 具體使用,這里分享一下 docker 是怎么使用 overlayfs。

大致流程

每一個 Docker image 都是由一系列的 read-only layers 組成:

  • image layers 的內(nèi)容都存儲在 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 內(nèi)核 3.18 把 overlay 納入其中,overlay 的地位變得更重。

docker info命令可以查看 docker 的文件系統(tǒng)。

$ docker info
# ...
 Storage Driver: overlay2
#...

比如這里用的就是 overlay2。

例如,假設(shè)我們有一個由兩層組成的容器鏡像:

   layer1:                 layer2:
    /etc                    /bin
      myconf.ini              my-binary

然后,在容器運(yùn)行時(shí)將把這兩層作為 lower 目錄,創(chuàng)建一個空upper目錄,并將其掛載到某個地方:

sudo mount \
            -t overlay \
            overlay \
            -o lowerdir=/layer1:/layer2,upperdir=/upper,workdir=/work \
            /merged

最后將/merged用作容器的 rootfs。

這樣,容器中的文件系統(tǒng)就完成了。

具體分析

以構(gòu)建鏡像方式演示以下 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

開始構(gòu)建:

$ 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

查看構(gòu)建好的鏡像:

$ 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 標(biāo)記的 layer 是自 Docker 1.10 之后,一個鏡像的 image layer image history 數(shù)據(jù)都存儲在 個文件中導(dǎo)致的,這是 Docker 官方認(rèn)為的正常行為。

可以看到,290d8cc1f75a 這一層在最上面,只用了 12Bytes,而下面的兩層都是共享的,這也證明了 AUFS 是如何高效使用磁盤空間的。

然后去找一下具體的文件:

docker 默認(rèn)的存儲目錄是/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

在這里,我們只關(guān)心imageoverlay2就足夠了。

  • image:鏡像相關(guān)
  • overlay2:docker 文件所在目錄,也可能不叫這個名字,具體和文件系統(tǒng)有關(guān),比如可能是 aufs 等。

先看 image目錄:

docker 會在/var/lib/docker/image目錄下按每個存儲驅(qū)動的名字創(chuàng)建一個目錄,如這里的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

這里的關(guān)鍵地方是imagedblayerdb目錄,看這個目錄名字,很明顯就是專門用來存儲元數(shù)據(jù)的地方。

  • layerdb:docker image layer 信息
  • imagedb:docker image 信息

因?yàn)?docker image 是由 layer 組成的,而 layer 也已復(fù)用,所以分成了 layerdb 和 imagedb。

先去 imagedb 看下剛才構(gòu)建的鏡像:

$  cd overlay2/imagedb/content/sha256
$ ls
[root@iZ2zefmrr626i66omb40ryZ sha256]# ls
0c7ea9afc0b18a08b8d6a660e089da618541f9aa81ac760bd905bb802b05d8d5  61ad638751093d94c7878b17eee862348aa9fc5b705419b805f506d51b9882e7
// .... 省略
b20b605ed599feb3c4757d716a27b6d3c689637430e18d823391e56aa61ecf01
60d84e80b842651a56cd4187669dc1efb5b1fe86b90f69ed24b52c37ba110aba  ba6acccedd2923aee4c2acc6a23780b14ed4b8a5fa4e14e252a23b846df9b6c1

可以看到,都是 64 位的 ID,這些就是具體鏡像信息,剛才構(gòu)建的鏡像 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,這里主要關(guān)注 rootfs:

# 和 docker inspect 命令顯示的內(nèi)容差不多
// ...
"rootfs":{"type":"layers","diff_ids":
[
"sha256:9f54eef412758095c8079ac465d494a2872e02e90bf1fb5f12a1641c0d1bb78b",
"sha256:b3cce2ce0405ffbb4971b872588c5b7fc840514b807f18047bf7d486af79884c"
]
}
// ...

可以看到 rootfs 的 diff_ids 是一個包含了兩個元素的數(shù)組,這兩個元素就是組成 hello-ubuntu 鏡像的兩個 Layer 的diffID

從上往下看,就是底層到頂層,即9f54eef412...是 image 的最底層。

然后根據(jù) layerID 去layerdb目錄尋找對應(yīng)的 layer:

[root@iZ2zefmrr626i66omb40ryZ overlay2]# tree -L 2 layerdb/
layerdb/
├── mounts
├── sha256
└── tmp

在這里我們只管mountssha256兩個目錄,先打印以下 sha256 目錄

$ cd /var/lib/docker/image/overlay2/layerdb/sha256/
$ ls
05dd34c0b83038031c0beac0b55e00f369c2d6c67aed11ad1aadf7fe91fbecda
// ... 省略
6aa07175d1ac03e27c9dd42373c224e617897a83673aa03a2dd5fb4fd58d589f

可以看到,layer 里也是 64 位隨機(jī) ID 構(gòu)成的目錄,找到剛才 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,用于計(jì)算 ChainID
  • size:當(dāng)前 layer 的大小

docker 使用了 chainID 的方式來保存 layer,layer.ChainID 只用本地,根據(jù) layer.DiffID 計(jì)算,并用于 layerdb 的目錄名稱。

chainID 唯一標(biāo)識了一組(像糖葫蘆一樣的串的底層)diffID 的 hash 值,包含了這一層和它的父層(底層),

  • 當(dāng)然這個糖葫蘆可以有一顆山楂,也就是 chainID(layer0)==diffID(layer0);
  • 對于多顆山楂的糖葫蘆,ChainID(layerN) = SHA256hex(ChainID(layerN-1) + " " + DiffID(layerN))。
# 查看 diffID,
$ cat diff
sha256:9f54eef412758095c8079ac465d494a2872e02e90bf1fb5f12a1641c0d1bb78b

由于這是 layer0,所以 chainID 就是 diffID,然后開始計(jì)算 layer1 的 chainID:

ChainID(layer1) = SHA256hex(ChainID(layer0) + " " + DiffID(layer1))

layer0 的 chainID 是9f54...,而 layer1 的 diffID 根據(jù) rootfs 中的數(shù)組可知,為b3cce...

計(jì)算 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
# 根據(jù)這個大小可以知道,就是hello-ubuntu 鏡像的最上面層 layer
[root@iZ2zefmrr626i66omb40ryZ 6613b10b697b0a267c9573ee23e54c0373ccf72e7991cf4479bd0b66609a631c]$ cat size
12
# 查看 cache-id 找到 文件系統(tǒng)中的具體位置
[root@iZ2zefmrr626i66omb40ryZ 6613b10b697b0a267c9573ee23e54c0373ccf72e7991cf4479bd0b66609a631c]$ cat cache-id
83b569c0f5de093192944931e4f41dafb2d7f80eae97e4bd62425c20e2079f65

根據(jù) cache-id 進(jìn)入具體數(shù)據(jù)存儲目錄:

格式為 /var/lib/docker/overlay2/<cache-id>

# 進(jìn)入剛才生成的目錄
$ 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 就在這里。


如果你對云原生技術(shù)充滿好奇,想要深入了解更多相關(guān)的文章和資訊,歡迎關(guān)注微信公眾號。

搜索公眾號【探索云原生】即可訂閱

分享到:
標(biāo)簽:Docker 探索 服務(wù)器 解密 魔法
用戶無頭像

網(wǎng)友整理

注冊時(shí)間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定