iT邦幫忙

2022 iThome 鐵人賽

DAY 6
0
DevOps

那些關於 docker 你知道與不知道的事系列 第 6

Day 06: 來玩一下 docker image layer

  • 分享至 

  • xImage
  •  

實驗 1

今天想做一個有點調皮的實驗,在上一篇中,我們用 nginx 這個 image 啟動了一個 container,在裡面放了一個 a.txt 的檔案後,將這個 container commit 成一個新的 image mynginx:a。今天就讓我們用 mynginx:a 這個 image 啟動一個 container,並且驗證一下在這個 container 裡是否有 a.txt 這個檔案及其內容:

$ docker run -it --rm mynginx:a /bin/bash
root@330b823440a9:/# cat a.txt
a

如我們預期的,有 a.txt 這個檔案,且內容也符合。用另外一個 terminal 先回到 Host,讓我們去編輯一下 /var/lib/docker/overlay2/e6f2ed0e6d55115918467a74b4dfab3f3423c346cccdbe68763de8727061bf20/diff 裡的這個 a.txt,如果在裡面多加上一行字之類的,注意,這邊會需要用 root 權限才能操作:

$ echo "b" >> /var/lib/docker/overlay2/e6f2ed0e6d55115918467a74b4dfab3f3423c346cccdbe68763de8727061bf20/diff/a.txt

$ cat /var/lib/docker/overlay2/e6f2ed0e6d55115918467a74b4dfab3f3423c346cccdbe68763de8727061bf20/diff/a.txt
a
b

修改完之後,回到剛剛啟動的那個 container,再印出一次 a.txt:

root@1c77ff7fbaaa:/# cat a.txt
a
b

欸,b 也跟著出現了!那如果我們修改的是 container 裡的 a.txt 呢?

root@1c77ff7fbaaa:/# echo "c" >> a.txt
root@1c77ff7fbaaa:/# cat a.txt
a
b
c

回到 Host,查看一下 Host 中的 a.txt 的內容:

$ cat /var/lib/docker/overlay2/e6f2ed0e6d55115918467a74b4dfab3f3423c346cccdbe68763de8727061bf20/diff/a.txt
a
b

只有 a 跟 b,沒有 c 喔!這時候,讓我們在 Host 中的 a.txt 加上更多內容:

$ echo "d" >> /var/lib/docker/overlay2/e6f2ed0e6d55115918467a74b4dfab3f3423c346cccdbe68763de8727061bf20/diff/a.txt

$ cat /var/lib/docker/overlay2/e6f2ed0e6d55115918467a74b4dfab3f3423c346cccdbe68763de8727061bf20/diff/a.txt
a
b
d

回到 container 中,查看一下 a.txt:

# cat a.txt
a
b
c

發現 d 不會像剛剛的 b 一樣出現在 container 的 a.txt 中,為什麼會有不一樣的情況呢?


上述的步驟比較多,我們來整理一下觀察的結果:

  1. mynginx:a 啟動的 container 中,會有 a.txt 這個檔案,且內容會跟我們在這個 image 的 UpperDir 檔案夾中的 a.txt 一模一樣。
  2. 當 a.txt 沒有在 container 中被修改時,在 Host 中對 a.txt 進行修改,都會反映在 container 中的 a.txt。
  3. 當 a.txt 在 container 中被修改後,在 Host 中對 a.txt 進行的修改,就再也不會反映到 container 中了。

實驗 2

重新用 mynginx:a 啟動一個新的 container,並且觀察 a.txt,其內容應該會是我們在上一個實驗中,最後對 Host 裡的 a.txt 編輯的結果:

$ docker run -it --rm --name nginx-a1 mynginx:a /bin/bash
root@cffbff10b148:/# cat a.txt
a
b
d

回到 Host,將這個新的 container commit 成另外一個新的 image mynginx:a1,用 inspect 去查看這個新的 image,會發現這個新的 image 的 RootFSGraphDriver 這兩個區塊的內容跟 mynginx:a 一模一樣。


實驗 3

重新用 mynginx:a 啟動一個新的 container,這次我們對 a.txt 做一些編輯,例如加上一個 x:

$ docker run -it --rm --name nginx-a2 mynginx:a /bin/bash
root@33b776b69eea:/# cat a.txt
a
b
d
root@33b776b69eea:/# echo "x" >> a.txt
root@33b776b69eea:/# cat a.txt
a
b
d
x

回到 Host,將這個新的 container commit 成另外一個新的 image mynginx:a2,用 inspect 去查看這個新的 image,會發現這個新的 image 的 RootFSGraphDriver,如預期地多了一層 layer,一樣去 mynginx:aUpperDir 看一下,會發現裡頭一樣有一個 a.txt,且其內容為:

$ docker image inspect --format='{{json .GraphDriver}}' mynginx:a2 | jq
{
  "Data": {
    "LowerDir": "...略",
    "MergedDir": "略",
    "UpperDir": "/var/lib/docker/overlay2/8aa9e16514e13409d7e335a586a0a9f79d3c44b00e0d3492943f66b74125011a/diff",
    "WorkDir": "略"
  },
  "Name": "overlay2"
}

$ cat /var/lib/docker/overlay2/8aa9e16514e13409d7e335a586a0a9f79d3c44b00e0d3492943f66b74125011a/diff/a.txt
a
b
d
x

實驗 4

重新用 mynginx:a 啟動一個新的 container,這次我們不對 a.txt 進行編輯,但在這個 container 裡增加一個新檔案 b.txt:

$ docker run -it --rm --name nginx-b mynginx:a /bin/bash
root@ef95ee841c42:/# cat a.txt
a
b
d
root@ef95ee841c42:/# touch b.txt
root@ef95ee841c42:/# echo "B" > b.txt
root@ef95ee841c42:/# cat b.txt
B

然後一樣 commit 成一個新的 image mynginx:b:

$ docker commit nginx-b mynginx:b
sha256:7ec241c60bc868acd1daaa18abce0472c8c314e25892fcfcd70dd0c92a8d8c2c

# 觀察 GraphDriver 
$ docker image inspect --format='{{json .GraphDriver}}' mynginx:b | jq
{
  "Data": {
    "LowerDir": "/var/lib/docker/overlay2/e6f2ed0e6d55115918467a74b4dfab3f3423c346cccdbe68763de8727061bf20/diff:/var/lib/docker/overlay2/8b0ad5ef739a7bb36a94fafce200ff939055225d5bcfd43b837ec3a5e8e595d6/diff:/var/lib/docker/overlay2/b55fadceebc53ee1e133343d57bcb70b4a96659ebb0a4c83ffcf27a02fe495ee/diff:/var/lib/docker/overlay2/1d05141f1e9f2fbc9bdfb87a681976ce7db6f1dae3c12a6d94c00197e07da019/diff:/var/lib/docker/overlay2/c5dee5abf71f4c0ecb219c68f19ca56f64b0400739319ed482994fb58c297f79/diff:/var/lib/docker/overlay2/ed5b345b9d1a113c250527826f268a24e556fc67314340a6082b9627bf99fc36/diff:/var/lib/docker/overlay2/2607ebf4a87c9a99966ad99c7c096d541114a3b4f75ab25e2bac3bf614f3485b/diff",
    "MergedDir": "/var/lib/docker/overlay2/c4186bea7547109e50df09d0c10e4ecd3d7cf4ac554812d5d3b95ab0d5ea6a88/merged",
    "UpperDir": "/var/lib/docker/overlay2/c4186bea7547109e50df09d0c10e4ecd3d7cf4ac554812d5d3b95ab0d5ea6a88/diff",
    "WorkDir": "/var/lib/docker/overlay2/c4186bea7547109e50df09d0c10e4ecd3d7cf4ac554812d5d3b95ab0d5ea6a88/work"
  },
  "Name": "overlay2"
}

$ sudo ls var/lib/docker/overlay2/c4186bea7547109e50df09d0c10e4ecd3d7cf4ac554812d5d3b95ab0d5ea6a88/diff
b.txt

不再出現 a.txt,但會有剛剛新加上去的 b.txt。


實驗做到這裡,目前的 image layer 已經變成了:
https://ithelp.ithome.com.tw/upload/images/20220921/20151857s0UyWEuTfk.png

  • 在 image mynginx:aUpperDir 中會有一個 a.txt。
  • 在 image mynginx:a2UpperDir 中會有一個 a.txt,內容跟 image mynginx:a 中的不一樣。
  • 在 image mynginx:bUpperDir 中沒有 a.txt,但會有新加上去的 b.txt。

這些是我們觀察到的結果,但到底原理是什麼呢?這些 layers 又是怎麼堆疊成我們在 container 裡看到的樣子呢?這個就讓我們靜待下一篇嚕。


上一篇
Day 05: 什麼是 image layer?
下一篇
Day 07: 什麼是 overlay2?
系列文
那些關於 docker 你知道與不知道的事32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言