在 Docker 環境中部署 Python 應用程式時,常常會遇到映像建置時間過長或因 gcc 等編譯器的依賴問題而建置失敗的情況。此時,最有效的解決方案之一就是使用 Python Wheel

本文將介紹 Python Wheel 的概念和優勢,以及如何在 Dockerfile 中應用其優化建置過程。


1. Python Wheel 是什麼?



Wheel(.whl) 是 Python 的 二進位發布格式 (Built Distribution)

一般來說,Python 套件以兩種形式進行發佈。

  1. Source Distribution (sdist, .tar.gz): 以源代碼的形式發佈。安裝時需要在用戶的計算機上進行編譯(Build)過程。

  2. Built Distribution (bdist_wheel, .whl): 以預編譯的二進位形式發佈。安裝時只需複製文件即可完成,而無需額外的編譯。

簡單來說,源發佈版就像是「需要組裝的家具」,而 Wheel 則是「已完成的家具」。使用 Wheel 時,無需組裝時間和工具(編譯器)。


2. 與一般 pip install 的區別

當我們執行經常使用的 pip install <package> 命令時,內部以以下的優先順序運作。

  1. 如果存在 Wheel 檔案: 下載該二進位檔並立即安裝。(速度非常快)

  2. 如果沒有 Wheel 檔案: 下載源文件 (tar.gz),然後在本地環境中進行編譯(Build)並安裝。(速度慢,需要編譯工具)

區別摘要表

分類 Source Distribution (sdist) Wheel (whl)
副檔名 .tar.gz, .zip .whl
安裝過程 下載 -> 編譯 -> 安裝 下載 -> 安裝
安裝速度 慢(需要編譯時間) 非常快
需要工具 編譯器 (gcc, g++, 標頭文件等) (只需有 pip 即可)
OS 依賴性 依據編譯時的環境 受限於已建置的 OS/架構

3. 在 Dockerfile 中使用 Wheel 的原因(優勢)



在 Docker 環境中,特別是 Multi-stage Build(多階段建置) 中使用 Wheel 有以下明確的優勢。

  1. 建置速度顯著提升: 不必每次都編譯如 pandasnumpy 等用 C/C++ 編寫的重型庫。

  2. 映像大小輕量化: 最終執行映像(Runtime Image)中無需包含像 gccbuild-essential 等重型編譯工具。

  3. 安全性保障: 防止因網路問題或外部儲存庫的暫時故障導致建置失敗,並且可以使用本地預先建置的檔案。


4. Dockerfile 的撰寫與用法

利用 Wheel 進行的 Docker 建置主要是在 Builder 階段 創建 Wheel 檔,然後在 Final 階段 將其取出並安裝。

範例:利用 Multi-stage Build 的 Dockerfile

以下是一個有效率安裝依賴 C 庫的套件的模式。

# [Stage 1] Builder: 創建 Wheel 檔
FROM python:3.9-slim as builder

# 安裝編譯所需的必要套件(不包含在最終映像中)
RUN apt-get update && apt-get install -y \
    build-essential \
    gcc \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# 複製 requirements.txt
COPY requirements.txt .

# 使用 pip wheel 命令在 /wheels 目錄中創建 .whl 檔
# -w: 指定儲存 wheel 檔的路徑
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /app/wheels -r requirements.txt


# [Stage 2] Final: 執行映像
FROM python:3.9-slim

WORKDIR /app

# 僅複製 Builder 階段生成的 Wheel 檔
COPY --from=builder /app/wheels /wheels
COPY --from=builder /app/requirements.txt .

# 使用 Wheel 檔安裝套件
# --no-index: 忽略 PyPI 指數,僅尋找本地檔案
# --find-links: 指定尋找要安裝的套件的路徑
RUN pip install --no-cache --no-index --find-links=/wheels -r requirements.txt \
    && rm -rf /wheels

# 複製應用程式代碼
COPY . .

CMD ["python", "main.py"]

核心命令解釋

  • pip wheel: 不安裝套件,而是生成適合環境的 .whl 檔並儲存到指定的目錄。

  • --wheel-dir: 生成的 Wheel 檔儲存的位置。

  • --find-links=/wheels: 指示在指定的本地路徑尋找套件,而不是從 PyPI 伺服器(互聯網)下載。


結語

利用 Python Wheel 進行 Docker 建置幾乎是必不可少的優化技巧。特別是在 CI/CD 管道中出現重復性建置的環境,僅透過縮短建置時間和減小映像大小就能獲得顯著的成本節省效果。

如果您的 Dockerfile 中包含安裝 gcc 的過程,請考慮轉向使用 Wheel 進行的多階段建置。

python-wheel-concept-image