隨著容器化應用日益普及,如何有效控制映像檔大小成為關鍵。傳統 Dockerfile 雖方便,但彈性有限。Buildah 作為新興工具,以其無 Daemon 模式和分層控制能力,為構建輕量級容器映像檔提供更最佳化的解決方案。它允許開發者以更程式化的方式控制映像檔的每一層,避免不必要的檔案和依賴,從而顯著縮減映像檔體積,提升佈署效率。更重要的是,Buildah 與 Podman 的相容性,使其能無縫整合到現有的容器生態系統中,簡化開發流程。本文將以一個 Python 應用為例,示範如何使用 Buildah 從零構建一個精簡的容器映像檔,並探討其在實際應用中的優勢。
Buildah:從零開始開發輕量級容器映像檔
在使用容器技術時,我們經常需要客製化容器映像檔以滿足特定需求。雖然 Dockerfile 是一個常見的選擇,但 Buildah 提供了更靈活的方式,讓我們可以從頭開始構建容器映像檔,實作更小的體積和更高的安全性。
為何選擇 Buildah?我的容器映像檔瘦身之旅
在過去,我曾使用 Dockerfile 構建容器映像檔,但隨著專案規模的增長,映像檔體積變得越來越大,佈署時間也隨之增加。為了最佳化映像檔大小,我開始研究 Buildah,發現它允許我逐步構建映像檔,並精確控制每一層的內容。
Buildah 的主要優勢在於:
- 無 Daemon 模式: Buildah 不需要持續執行的 Daemon 行程,降低了資源消耗和潛在的安全風險。
- 靈活性: Buildah 允許我們以程式化的方式構建映像檔,可以輕鬆地整合到現有的 CI/CD 流程中。
- 分層控制: Buildah 允許我們精確控制映像檔的每一層,從而實作更小的映像檔體積。
環境準備:Buildah 的根本
Buildah 的組態與 Podman 分享,這意味著我們可以利用 Podman 的組態檔案來客製化 Buildah 的行為。以下是一些重要的組態檔案:
/usr/share/containers/mounts.conf:定義自動掛載到 Buildah 工作容器內的檔案和目錄。/etc/containers/registries.conf:管理允許存取的映像檔倉函式庫,用於映像檔搜尋、提取和推播。/usr/share/containers/policy.json:定義映像檔簽章驗證行為的 JSON 組態檔案。/usr/share/containers/seccomp.json:定義容器化行程允許和禁止的系統呼叫的 JSON 組態檔案。
Buildah 的三種武器:構建策略解析
Buildah 提供了三種主要的構建策略:
- 從現有基礎映像檔開始: 在現有映像檔的基礎上進行修改和擴充套件。
- 從頭開始構建: 從一個空的容器映像檔開始,逐步增加所需的元件。
- 從 Dockerfile 構建: 使用 Dockerfile 作為構建藍圖。
在本文中,玄貓將重點介紹從頭開始構建容器映像檔的策略,因為它提供了最大的靈活性和控制力。
實戰演練:開發一個極簡 Python 容器
以下是一個使用 Buildah 從頭開始構建一個極簡 Python 容器的範例:
#!/bin/bash
# 定義基礎映像檔和目標映像檔
BASE_IMAGE="alpine:latest"
TARGET_IMAGE="python3-minimal"
# 檢查是否以 root 身份執行
if [ $UID != 0 ]; then
echo "### 以非特權使用者身份執行構建測試"
else
echo "### 以 root 身份執行構建測試"
fi
# 建立工作容器
echo "### 測試容器建立"
container=$(buildah from $BASE_IMAGE)
if [ $? -ne 0 ]; then
echo "Error initializing working container"
fi
# 在容器中安裝 Python 及其相依套件
echo "### 測試 run 命令"
buildah run $container apk add --update python3 py3-pip
if [ $? -ne 0 ]; then
echo "Error on run build action"
fi
# 將容器提交為映像檔
echo "### 測試映像檔提交"
buildah commit $container $TARGET_IMAGE
if [ $? -ne 0 ]; then
echo "Error committing final image"
fi
# 移除工作容器
echo "### 移除工作容器"
buildah rm $container
if [ $? -ne 0 ]; then
echo "Error removing working container"
fi
echo "### 構建測試成功完成!"
exit 0
內容解密:程式碼逐行拆解
#!/bin/bash: 指定使用 Bash shell 執行此指令碼。BASE_IMAGE="alpine:latest": 定義基礎映像檔為 Alpine Linux 的最新版本。Alpine Linux 是一個輕量級的 Linux 發行版,非常適合用於構建小型容器映像檔。TARGET_IMAGE="python3-minimal": 定義目標映像檔的名稱為python3-minimal。if [ $UID != 0 ]; then ... else ... fi: 檢查目前使用者是否為 root。如果不是 root,則顯示以非特權使用者身份執行構建測試的訊息;否則,顯示以 root 身份執行構建測試的訊息。container=$(buildah from $BASE_IMAGE): 使用buildah from命令從指定的基礎映像檔建立一個新的工作容器。buildah from命令會建立一個可寫入的容器層,我們可以在其中進行修改。buildah run $container apk add --update python3 py3-pip: 使用buildah run命令在工作容器中執行apk add命令,以安裝 Python 3 及其相依套件。apk add是 Alpine Linux 的套件管理器,用於安裝、更新和移除軟體套件。buildah commit $container $TARGET_IMAGE: 使用buildah commit命令將工作容器提交為一個新的映像檔。buildah commit命令會將容器的內容儲存為一個新的映像檔層,並將其增加到映像檔倉函式庫中。buildah rm $container: 使用buildah rm命令移除工作容器。buildah rm命令會刪除容器及其所有相關的資源。exit 0: 表示指令碼成功執行完成。
構建完成後,可以使用 Podman 執行該映像檔:
$ podman run -it python3-minimal /usr/bin/python3
Python 3.9.5 (default, May 12 2021, 20:44:22)
[GCC 10.3.1 20210424] on linux
Type "help", "copyright", "credits" or "license" for more
information.
>>>
容器映像檔的進階客製化
除了安裝軟體套件外,我們還可以透過以下方式客製化容器映像檔:
- 增加檔案: 使用
buildah copy命令將檔案從主機複製到容器中。 - 設定環境變數: 使用
buildah config --env命令設定容器的環境變數。 - 執行自定義指令: 使用
buildah run命令執行任何可以在容器中執行的指令。