鏡像分層原理及容器層寫時複製

一、鏡像分層與容器層

在進行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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章