2.1 映象

版本說明:本節範例基於 Docker v29.x 編寫。範例中使用的映象標籤(如 ubuntu:24.04nginx:latest)為示範用途,建議查閱 Docker Hub 或相應映象的官方頁面確認最新可用版本。

Docker 映象作為容器執行的基石,其設計理念和實現機制至關重要。本節將深入探討映象的本質、與作業系統的關係、內容構成以及核心的分層儲存機制。

2.1.1 一句話理解映象

Docker 映象是一個只讀的樣板,包含了執行應用所需的一切:程式碼、執行時、函式庫、環境變數和設定檔案。 如果用一個類比:映象就像是一張光碟或 ISO 檔案。你可以用同一張光碟在不同電腦上安裝系統,而光碟本身不會被修改。同樣,一個映象可以建立多個容器,而映象本身保持不變。

2.1.2 映象與作業系統的關係

我們都知道,作業系統分為 核心使用者空間

flowchart TD subgraph UserSpace ["使用者空間"] direction TB App["應用程式、工具、函式庫、設定檔案...
(這部分被打包成 Docker 映象)"] end subgraph KernelSpace ["Linux 核心"] direction TB Kernel["容器共享宿主機的核心"] end UserSpace --- KernelSpace

對於 Linux 而言,核心啟動後會掛載 root 檔案系統來提供使用者空間支援。Docker 映象 本質上就是一個 root 檔案系統。

例如,官方映象 ubuntu:24.04 包含了一套完整的 Ubuntu 24.04 最小系統的 root 檔案系統——但 不包含 Linux 核心 (因為容器共享宿主機的核心)。

2.1.3 映象包含什麼?

Docker 映象是一個特殊的檔案系統,包含:

內容型別 範例
程式檔案 應用二進位檔案、Python/Node 直譯器
函式庫檔案 libc、OpenSSL、各種依賴庫
設定檔案 nginx.conf、my.cnf 等
環境變數 PATH、LANG 等預設值
元資料 啟動指令、暴露連接埠、資料卷定義

關鍵屬性

  • ✅ 映象是 只讀
  • ✅ 映象 不包含 動態資料
  • ✅ 映象建立後 內容不會改變

2.1.4 分層儲存:映象的核心設計

映象的分層儲存機制是 Docker 最具創新性的屬性之一。透過 Union FS 技術,Docker 能夠高效地建立和管理映象。

為什麼需要分層?

筆者認為,分層儲存是 Docker 最巧妙的設計之一。

假設你有三個應用,都基於 Ubuntu 執行:

flowchart TD subgraph Traditional ["傳統方式(不分層)總計: 1.5GB ❌"] direction LR AppA_Trad["App A
Ubuntu 500MB"] AppB_Trad["App B
Ubuntu 500MB"] AppC_Trad["App C
Ubuntu 500MB"] end subgraph DockerLayered ["Docker 分層方式 總計: 620MB ✅"] direction TB subgraph Apps ["應用層"] direction LR AppA["App A 50MB"] AppB["App B 30MB"] AppC["App C 40MB"] end Ubuntu["Ubuntu
(共享)500MB"] AppA --> Ubuntu AppB --> Ubuntu AppC --> Ubuntu end

分層是如何工作的?

筆者用一個更貼近最佳實踐的 Dockerfile 來解釋分層:

FROM ubuntu:24.04                              # 第 1 層:基礎系統(約 78MB)
RUN apt-get update && apt-get install -y nginx # 第 2 層:更新索引並安裝 nginx
COPY app.conf /etc/nginx/                      # 第 3 層:複製設定檔案

這裡特意把 apt-get updateapt-get install 放在同一個 RUN 裡,避免建立快取導致套件索引過期。

建立後的映象結構:

flowchart TD Layer3["第 3 層: COPY app.conf (只讀)
← 最新新增的層"] Layer2["第 2 層: nginx 安裝檔案與套件索引 (只讀)"] Layer1["第 1 層: Ubuntu 基礎系統 (只讀)
← 基礎映象層"] Layer3 --> Layer2 --> Layer1

每一層的特點:

  • 只讀:建立完成後不可修改
  • 可共享:多個映象可以共享相同的層
  • 有快取:未變化的層不會重新建立

分層儲存的 『陷阱』

⚠️ 筆者特別提醒:理解這一點可以幫你避免建立出臃腫的映象。關鍵原理:每一層的檔案變化會被記錄,但 刪除操作只是標記,不會真正減小映象體積

## 錯誤示範 ❌

FROM ubuntu:24.04
RUN apt-get update
RUN apt-get install -y build-essential  # 安裝編譯工具(約 200MB)
RUN make && make install                  # 編譯應用
RUN apt-get remove build-essential        # 試圖刪除編譯工具

## 結果:映象仍然包含 200MB 的編譯工具!
## 正確做法 ✅

FROM ubuntu:24.04
RUN apt-get update && \
    apt-get install -y build-essential && \
    make && make install && \
    apt-get remove -y build-essential && \
    apt-get autoremove -y && \
    rm -rf /var/lib/apt/lists/*

## 在同一層完成安裝、使用、清理

2.1.5 檢視映象的建立歷史

## 檢視映象的歷史(每層的建立記錄)

$ docker history nginx:latest

IMAGE          CREATED       CREATED BY                                      SIZE
a6bd71f48f68   2 weeks ago   CMD ["nginx" "-g" "daemon off;"]                0B
<missing>      2 weeks ago   STOPSIGNAL SIGQUIT                              0B
<missing>      2 weeks ago   EXPOSE map[80/tcp:{}]                           0B
<missing>      2 weeks ago   ENTRYPOINT ["/docker-entrypoint.sh"]            0B
<missing>      2 weeks ago   COPY 30-tune-worker-processes.sh /docker-ent…   4.62kB
...

需要注意:docker history 展示的是映象的建立歷史。像 CMDENTRYPOINTEXPOSESTOPSIGNAL 這類 0B 項主要是映象設定元資料,並不等同於新增了可見的檔案系統內容;真正佔用空間的通常是 RUNCOPYADD 等帶來的檔案變化。

2.1.6 映象的標識

Docker 映象有多種標識方式:

1. 映象名稱和標籤

格式:[倉庫地址/]倉庫名[:標籤]

## 完整格式

registry.example.com/myproject/myapp:v1.2.3

## 簡寫(使用 Docker Hub)

nginx:1.28
ubuntu:24.04

## 省略標籤(預設使用 latest)

nginx  # 等同於 nginx:latest

2. 映象 ID:Content-Addressable 標識

每個映象有一個基於內容計算的唯一 ID:

$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    a6bd71f48f68   2 weeks ago    187MB
ubuntu       24.04     ca2b0f26964c   3 weeks ago    78.1MB

3. 映象摘要

更精確的標識,基於映象內容的 SHA256 雜湊:

$ docker images --digests
REPOSITORY  TAG     DIGEST                                                                    IMAGE ID
nginx       latest  sha256:6db391d1c0cfb30588ba0bf72ea999404f2764184d8b8d10d89e8a9c6... a6bd71f48f68

💡 筆者建議:在生產環境使用映象摘要而非標籤,因為標籤可以被覆蓋,但摘要是不可變的。

2.1.7 映象的來源

Docker 映象可以透過以下方式獲取:

方式 說明 範例
從 Registry 拉取 最常用的方式 docker pull nginx
從 Dockerfile 建立 自定義映象 docker build -t myapp .
從容器送出 儲存容器狀態 (不推薦) docker commit
從檔案匯入 離線傳輸 docker load < image.tar
第 10 页,共 196 页
使用 mdPress 构建