Docker拉取映象時的疑惑

Aicnal發表於2024-08-11

Docker拉取映象時的疑惑

不知道你在拉取映象的時候會不會有這樣的疑惑——我不是隻拉取了一個映象嘛,為什麼會出現這麼多的東西

Docker中Layer(層)的概念

在 Docker 中,映象(Image)是由多個層(Layer)組成的。這些層就像檔案系統的快照,每一層都記錄了從上一層開始的一系列變化。我們上面下載時候出現的ec99f8b99825就屬於一個層。

諸如 ec99f8b99825 的字串是層的唯一識別符號(Layer ID)。每一層都有一個獨特的 ID,用來識別和引用這一層。拉取映象時,Docker 會逐層下載這些層,並最終組合成一個完整的映象。

使用層對於Docker映象有以下好處:

  1. 共享和複用:如果不同的映象共享相同的基礎層,那麼這些層只需要下載和儲存一次,節省了磁碟空間和下載時間。
  2. 分層構建:Dockerfile 中的每一條指令(如 RUN, COPY, ADD 等)都會建立一個新的層。這樣如果你對 Dockerfile 進行了一些小的修改,Docker 只需要重建修改後的部分,而不需要重新構建整個映象。

Layer的建立

當你使用 Dockerfile 建立映象時,Docker 會按照 Dockerfile 中的每一條指令逐步構建映象。每一條指令都會生成一個新的層,這個層記錄了指令執行後檔案系統的變化。最終映象是由這些層按順序疊加而成。

例如你現在有一個Dockerfile

FROM ubuntu:20.04
RUN apt-get update
RUN apt-get install -y python3
COPY . /app
  • FROM ubuntu:20.04:這條指令會拉取一個基礎映象(ubuntu:20.04)。這個映象已經包含了作業系統的基本檔案系統,它是整個映象的基礎層。
  • RUN apt-get update:這條指令會更新包管理器的索引,並生成一個新的層,記錄了更新後的系統狀態。
  • RUN apt-get install -y python3:這條指令安裝 Python3,同樣會生成一個新的層,記錄安裝 Python3 後檔案系統的變化。
  • COPY . /app:這條指令將當前目錄下的所有檔案複製到映象中的 /app 目錄,生成一個新的層,記錄這些檔案的新增。

最終生成的映象由這幾層疊加而成,每一層都記錄了自上一個層以來的檔案系統的變化。

Cached layers (快取層)

當你執行構建時,構建器會嘗試重用早期構建中的層。如果影像的某個圖層未更改,則構建器會從構建快取中選取它。如果自上次構建以來某個層發生了更改,則必須重新構建該層以及後續的所有層。

這樣如果你對 Dockerfile 進行了一些小的修改,Docker 只需要重建修改後的部分,而不需要重新構建整個映象。

Layer的複用

這個其實算比較常見了,如果你拉取的映象共用同一Layer,那麼它不必重新拉取,而是可以複用。

每個層都有一個唯一的 ID,用來標識這一層。這個 ID 是透過對層內容進行雜湊計算生成的,因此相同內容的層總是會生成相同的 ID。

當你拉取一個映象時,Docker 會顯示每個層的 ID。例如,諸如 ec99f8b99825 的字串就是層的 ID。Docker 會逐層檢查本地是否已經有該層,如果有就會跳過下載,直接複用本地已有的層。如果沒有,則會從映象倉庫下載該層。

Layer的合併與檔案系統

當你拉取一個映象時,Docker 會從遠端倉庫逐層下載組成該映象的所有層。每個層下載完成後,Docker 會顯示該層的狀態,如 “下載完成”、“拉取完成”等。最終,這些層會在本地組合起來,形成完整的映象。

雖然映象由多個層組成,但在容器內,這些層會合併為一個統一的檔案系統。容器看到的檔案系統是這些層的疊加結果,每一層的更改會覆蓋上層的內容。例如,如果在後面的層中刪除或修改了檔案,容器內的檔案系統會反映這些變化,而不會看到原始的檔案。

如果你對類似的文章感興趣的話,歡迎訪問:小樹 | Docker拉取映象時的疑惑——Layer

參考文章:Docs Docker | Layer

相關文章