Buildah 提供了高度彈性的容器映像檔構建方式,尤其在追求極致精簡或需要深入掌控底層細節時,更能展現其優勢。本文將從零開始構建 Fedora 映像檔的例項出發,逐步引導讀者理解 Buildah 的核心概念。首先,我們將使用 buildah from scratch 建立一個空白容器,接著利用 dnf 安裝必要的套件,例如 bash 和 coreutils,並設定容器啟動後的執行指令。完成後,我們將使用 buildah commit 將容器儲存為映像檔,並探討如何使用 Podman 檢視映像檔的中繼資料,例如標籤、註解和歷史記錄。
雖然從零開始構建能完全掌控映像檔內容,但對於大多數應用場景,根據現有基礎映像檔並安裝所需套件更為實用。Buildah 支援此流程,並允許使用 fedora-minimal 等最小化基礎映像檔,有效減少映像檔體積。此外,本文將介紹如何利用 Dockerfile 簡化容器構建流程。我們將以一個建構 Web 伺服器的 Dockerfile 為例,示範如何使用 buildah build 命令,搭配 -f、-t 等引數,快速構建容器映像檔。同時,我們也將探討如何透過 Dockerfile 設定基礎映像檔、安裝套件、暴露連線埠以及設定容器啟動指令等操作,並說明如何使用 Podman 執行最終構建的映像檔。
開發容器:從零開始的 Buildah 之旅
在眾多容器構建策略中,如何選擇最適合的方案?這個問題沒有標準答案。首先,我們應積極尋找社群中是否有現成的映象能簡化構建流程;若無,則可考慮從零開始構建。此外,Dockerfile 也是不錯的選擇,它能讓你輕鬆與開發團隊或更廣泛的容器社群分享構建步驟。
簡要介紹到此,接下來讓我們進入實作環節!
從零開始構建映象:Buildah 實戰
在深入瞭解如何從零開始構建容器映象之前,讓我們先驗證 Buildah 是否正常運作。首先,檢查 Buildah 的映象快取是否為空:
# buildah images
REPOSITORY TAG IMAGE ID CREATED SIZE
# buildah containers -a
CONTAINER ID BUILDER IMAGE ID IMAGE NAME
CONTAINER NAME
重要提示
Podman 和 Buildah 共用相同的容器儲存空間。因此,如果你之前執行過本章或其他書籍中的範例,可能會發現容器儲存快取並非完全空白!
如前所述,Buildah 會輸出剛建立的工作容器名稱,方便我們將其儲存在環境變數中並隨時使用。現在,讓我們從零開始建立一個全新的容器:
# buildah from scratch
# buildah images
REPOSITORY TAG IMAGE ID CREATED SIZE
# buildah containers
CONTAINER ID BUILDER IMAGE ID IMAGE NAME
CONTAINER NAME
af69b9547db9 * scratch
working-container
正如你所見,我們使用了特殊的 from scratch 關鍵字,指示 Buildah 建立一個不含任何資料的空容器。執行 buildah images 命令後,你會發現這個特殊映象並未列出。
讓我們確認這個容器是否真的為空:
# buildah run working-container bash
2021-10-26T20:15:49.000397390Z: executable file 'bash' not
found in $PATH: No such file or directory
error running container: error from crun creating container for
[bash]: : exit status 1
error while running runtime: exit status 1
結果不出所料,在空容器中找不到可執行檔。這是因為工作容器是在一個空的檔案系統上建立的。
接下來,我們將示範如何輕鬆地填充這個空容器。在這個範例中,我們將直接與底層儲存互動,使用主機系統的套件管理器來安裝執行 Bash Shell 所需的二進位檔案和函式庫。
首先,指示 Buildah 掛載容器儲存空間並檢查其位置:
# buildah mount working-container
/var/lib/containers/storage/overlay/b5034cc80252b6f4af2155f
9e0a2a7e65b77dadec7217bd2442084b1f4449c1a/merged
小提示
如果在無根模式下啟動構建,Buildah 會在不同的名稱空間中執行掛載。因此,當使用 vfs 以外的驅動程式時,掛載的磁碟區可能無法從主機存取。
太棒了!現在我們找到了掛載點,可以利用主機套件管理器將所有需要的套件安裝到這個根資料夾中,這將成為容器映象的根路徑:
# scratchmount=$(buildah mount working-container)
# dnf install --installroot $scratchmount --releasever 34 bash
coreutils --setopt install_weak_deps=false -y
重要提示
如果在 Fedora 版本 34 以外的版本(例如 35)上執行上述命令,則需要匯入 Fedora 34 的 GPG 公開金鑰或使用 --nogpgcheck 選項。
首先,我們將冗長的目錄路徑儲存在環境變數中,然後執行 dnf 套件管理器,將剛取得的目錄路徑作為安裝根目錄,設定 Fedora 作業系統的版本,指定要安裝的套件(bash 和 coreutils),最後停用弱依賴性,並接受對系統的所有變更。
命令應以 Complete! 結尾。完成後,讓我們再次嘗試之前失敗的命令:
# buildah run working-container bash
bash-5.1# cat /etc/fedora-release
Fedora release 34 (Thirty Four)
成功了!我們剛在空的容器中安裝了 Bash Shell。現在,讓我們看看如何透過其他組態步驟完成映象建立。首先,我們需要為最終容器映象新增一個啟動後要執行的命令。為此,我們將建立一個包含一些基本命令的 Bash 指令碼檔案:
# cat command.sh
#!/bin/bash
cat /etc/fedora-release
/usr/bin/date
我們建立了一個 Bash 指令碼檔案,用於列印容器的 Fedora 版本和系統日期。在複製檔案之前,必須先授予執行許可權:
# chmod +x command.sh
現在,我們已將所有需要的基礎套件填入底層容器儲存空間,可以解除安裝 working-container 儲存空間,並使用 buildah copy 命令將檔案從主機注入到容器中:
# buildah unmount working-container
af69b9547db93a7dc09b96a39bf5f7bc614a7ebd29435205d358e09ac
99857bc
# buildah copy working-container ./command.sh /usr/bin
659a229354bdef3f9104208d5812c51a77b2377afa5ac819e3c3a1a2887eb9f7
buildah copy 命令讓我們能夠處理底層儲存,而無需擔心掛載或在後端處理。
現在,我們可以透過新增一些中繼資料來完成容器映象:
# buildah config --cmd /usr/bin/command.sh working-container
# buildah config --created-by "podman book example" working-
container
# buildah config --label name=fedora-date working-container
首先,我們使用 cmd 選項,然後新增一些描述性中繼資料。最後,我們可以將 working-container 提交到映象中!
# buildah commit working-container fedora-date
Getting image source signatures
Copying blob 939ac17066d4 done
Copying config e24a2fafde done
Writing manifest to image destination
Storing signatures
e24a2fafdeb5658992dcea9903f0640631ac444271ed716d7f749eea7a651487
讓我們清理環境並檢查主機中可用的容器映象:
# buildah rm working-container
af69b9547db93a7dc09b96a39bf5f7bc614a7ebd29435205d358e09ac99857bc
透過本文的實作,玄貓(BlackCat)帶領大家瞭解如何使用 Buildah 從零開始構建容器映象。這種方法雖然較為繁瑣,但能讓你更深入地理解容器的底層運作,並能最大程度地客製化映象內容。在實際應用中,你可以根據專案需求和團隊經驗,選擇最適合的容器構建策略。
開發容器映像檔:玄貓的Buildah實戰
在容器技術的世界裡,Buildah 提供了一種從頭開始構建容器映像檔的強大方式。雖然這種方法不常見,但在某些特定情境下,例如需要極度精簡映像檔或進行底層除錯時,它就顯得非常有用。
從零開始:容器映像檔的解構
讓我們從一個簡單的範例開始,一步一步地建立一個根據 Fedora 的容器映像檔,並在其中執行 date 指令:
# buildah from scratch
working-container
# buildah config --cmd /usr/bin/date $working-container
# buildah run $working-container -- dnf -y update
# buildah commit $working-container localhost/fedora-date
現在,我們可以檢查剛建立的容器映像檔的詳細資訊:
# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/fedora-date latest e24a2fafdeb5 About a minute ago 366 MB
# podman inspect localhost/fedora-date:latest
[...omitted output]
"Labels": {
"io.buildah.version": "1.23.1",
"name": "fedora-date"
},
"Annotations": {
"org.opencontainers.image.base.digest": "",
"org.opencontainers.image.base.name": ""
},
"ManifestType": "application/vnd.oci.image.manifest.v1+json",
"User": "",
"History": [
{
"created": "2021-10-26T21:16:48.777712056Z",
"created_by": "podman book example"
}
],
"NamesHistory": [
"localhost/fedora-date:latest"
]
從上面的輸出可以看到,容器映像檔包含大量的中繼資料,這些中繼資料可以告訴我們很多細節。其中一些是我們透過之前的指令設定的,例如 created_by、name 和 Cmd 標籤;其他標籤則由 Buildah 自動填充。
執行容器:驗證成果
最後,讓我們用 Podman 執行這個全新的容器映像檔!
# podman run -ti localhost/fedora-date:latest
Fedora release 34 (Thirty Four)
Tue Oct 26 21:18:29 UTC 2021
玄貓認為,從頭開始建立容器映像檔並不是一種典型的方法。在許多情況下,從一個作業系統基礎映像檔(例如 Fedora 或 Alpine)開始,然後使用這些映像檔中可用的相應套件管理器增加所需的套件就足夠了。
最小化映像檔:最佳實踐
有些 Linux 發行版還提供最小化的基礎容器映像檔(例如 fedora-minimal),它們減少了已安裝套件的數量以及目標容器映像檔的大小。
Dockerfile:玄貓的映像檔構建利器
正如本章前面所描述的,Dockerfile 是一種簡單的方式來建立和分享用於建立容器映像檔的構建步驟。因此,在網路上很容易找到大量的 Dockerfile 原始碼。
建立 Dockerfile:玄貓的Web伺服器範例
首先,我們需要建立一個簡單的 Dockerfile 來進行操作。以下是一個用於建立容器化 Web 伺服器的 Dockerfile 範例:
# Start from latest fedora container base image
FROM fedora:latest
MAINTAINER podman-book # this should be an email
# Update the container base image
RUN echo "Updating all fedora packages"; dnf -y update; dnf -y clean all
# Install the httpd package
RUN echo "Installing httpd"; dnf -y install httpd
# Expose the http port 80
EXPOSE 80
# Set the default command to run once the container will be started
CMD ["/usr/sbin/httpd", "-DFOREGROUND"]
在這個 Dockerfile 中,我們首先指定了基礎映像檔為最新的 Fedora 映像檔。然後,我們更新了基礎映像檔中的所有套件,並安裝了 httpd 套件。接著,我們宣告容器將監聽 80 埠,並設定容器啟動時要執行的預設指令。
使用 Buildah 構建映像檔:玄貓的實戰演練
正如本章前面所看到的,Buildah 提供了一個專用的 buildah build 指令,用於從 Dockerfile 啟動構建。
讓我們看看它是如何工作的:
# buildah build -f Dockerfile -t myhttpdservice .
STEP 1/6: FROM fedora:latest
Resolved "fedora" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull registry.fedoraproject.org/fedora:latest...
Getting image source signatures
Copying blob 944c4b241113 done
Copying config 191682d672 done
Writing manifest to image destination
Storing signatures
STEP 2/6: MAINTAINER podman-book # this should be an email
STEP 3/6: RUN echo "Updating all fedora packages"; dnf -y update; dnf -y clean all
Updating all fedora packages
Fedora 34 - x86_64 16 MB/s | 74 MB 00:04
...
STEP 4/6: RUN echo "Installing httpd"; dnf -y install httpd
Installing httpd
Fedora 34 - x86_64 20 MB/s | 74 MB 00:03
...
STEP 5/6: EXPOSE 80
STEP 6/6: CMD ["/usr/sbin/httpd", "-DFOREGROUND"]
COMMIT myhttpdservice
Getting image source signatures
Copying blob 7500ce202ad6 skipped: already exists
Copying blob 51b52d291273 done
Copying config 14a2226710 done
Writing manifest to image destination
Storing signatures
--> 14a2226710e
Successfully tagged localhost/myhttpdservice:latest
14a2226710e7e18d2e4b6478e09a9f55e60e0666dd8243322402ecf6fd1eaa0d
從上面的輸出可以看到,我們將以下選項傳遞給 buildah build 指令:
-f:用於定義 Dockerfile 的名稱。預設檔名為Dockerfile,因此在我們的例子中,可以省略這個選項,因為我們將檔案命名為預設名稱。-t:用於定義我們正在構建的映像檔的名稱和標籤。在我們的例子中,我們只定義了名稱。映像檔將預設標記為latest。- 最後,作為最後一個選項,我們需要設定 Buildah 需要工作並搜尋 Dockerfile 的目錄。在我們的例子中,我們傳遞了目前的
.目錄。
當然,這些並不是 Buildah 提供的唯一選項,可以用於組態構建。我們將在本文後面看到其中的一些選項。
透過本篇文章,玄貓希望能幫助大家更深入地瞭解如何使用 Buildah 構建容器映像檔。無論是從頭開始還是使用 Dockerfile,Buildah 都能提供強大的功能和靈活性,滿足不同的需求。