映象分層原理及容器層寫時複製

字母哥部落格發表於2022-05-09

一、映象分層與容器層

在進行docker pull 下載映象的時候,通過下圖可以看到映象是分層下載並解壓的。如nginx:1.20.2的映象,其映象是分為6層。

當我們執行一個新的容器的時候,實際上是在映象分層的基礎上新新增了一層:container layer(容器層)。之後所有容器執行時對檔案系統產生的修改實際都隻影響這一層。並且針對這一層所作的修改(寫操作),在容器重啟之後會全部丟失。所以說在使用docker的過程中,在需要修改執行時容器檔案資料的時候,儘量去重新構建映象而不是直接修改容器內檔案。如果重構映象解決不了的問題,使用資料卷。

構建映象的方法是通過Dockerfile定義,資料卷的使用詳解,專欄後續文章筆者會詳細介紹。

注意 :對於執行時的容器而言,映象層只讀的,容器層可讀也可寫。對於映象層的只讀檔案,容器層如果想做修改,實際上是進行了寫時複製操作。(下文介紹)。

二、為什麼會產生分層?

通過上文的介紹,我們已經知道映象是分層的,那麼映象分層的依據是什麼?或者說構建映象的時候究竟是什麼動作產生了分層?我們來看下面的這張圖,使用docker history檢視映象的構建歷史。

注意上圖中紅色邊框的部分,我們可以看到:在進行ADD、COPY、執行shell指令碼等操作的時候操作步驟對應的SIZE不等於0,正好是6個操作,和我們上文中nginx:1.20.2映象分層的數量是一樣的。所以我們可以做一個大膽的猜想:在映象構建過程中需要向映象寫入資料的時候會產生分層,一個寫操作指令產生一個分層。 大家可以自己去觀察更多的映象去驗證這個猜想。筆者要說的是:我讀過Dokcer的原始碼,所以這是一個可以被信任的結論。

上面的這張圖是nginx:1.20.2的Dockerfile(映象構建過程定義文件),也就是構建nginx:1.20.2映象的構建步驟定義文件(官方)。其中FROM(ADD)指令--新增基礎映象或檔案、RUN指令--執行命令列指令碼、COPY指令--檔案複製,這些都是寫操作命令,都會產生新的映象分層。

三、什麼是寫時複製?

上文中我們提到了一個概念:寫時複製。這個概念如果用專業名詞的方式說明還是比較難以理解,所以我用白話的方式說明一下。舉個例子:

  • 一個授課老師寫了一本練習冊(原始映象)。
  • 然後老師留作業了,練習冊第12頁。全班同學把練習冊的第12頁全都影印了一份,帶回家做作業。

老師的練習冊是原始文稿(正本)(原始文稿構建之後就只讀不寫,映象層檔案也是),同學們的練習冊是在需要使用到的時候影印出來的,並在影印本(副本)上完成作業書寫,不影響原來老師那本練習冊(正本)的內容。這個就是典型的“寫時複製”。
對於容器而言,複製出來的檔案在面向容器內的執行時軟體時,會覆蓋原始映象檔案(對於學生而言也只看自己複製出來那份--不要抬槓:抄作業的除外,不看老師的原始檔案)。也就是說發生寫時複製之後原始映象檔案被隱藏,容器讀寫操作都只認複製出來的副本檔案。注意:該副本檔案存在於容器層,容器重啟之後容器層重新建立,上一次容器執行時對於檔案的修改全部丟失!

歡迎關注我的部落格,更多精品知識合集

本文轉載註明出處(必須帶連線,不能只轉文字):字母哥部落格 - zimug.com

覺得對您有幫助的話,幫我點贊、分享!您的支援是我不竭的創作動力!。另外,筆者最近一段時間輸出瞭如下的精品內容,期待您的關注。

相關文章