# Podman Pod 設定 App Containers 啟動順序 ## 理解 OCI hooks `Container hooks` 是 `OCI` 規範中的一項功能,它允許使用者在 App Container 生命週期 (lifecycle) 的不同時間點,定義並執行特定的動作。 這些 `hook` 是指一些腳本 (`scripts`) 或指令 (`commands`),它們會在特定的事件發生時被執行,例如在 container 被建立 (`created`)、啟動 (`started`)、停止 (`stopped`) 或刪除 (`deleted`) 的前後。`Container hooks` 提供了一種擴充 container 行為的方法,可用於多種目的,包括設定 (`setup`)、配置 (`configuration`) 和清理 (`cleanup`) 等任務。 `OCI container hooks` 包含以下幾種類型: * **`precreate`**:這個 `hook` 會在 container 的設定檔產生之後,但在 container 真正啟動之前執行。 * **`prestart`**:這個 `hook` 會在 container 的主要程序 (`primary process`) 啟動**前**執行。它可以用來執行像是設定環境變數、配置網路設定或準備 container 的檔案系統 (`filesystem`) 等任務。 * **`poststart`**:這個 `hook` 會在 container 的主要程序 (`primary process`) 啟動**後**執行。它可用於執行那些需要在 container 開始運行後才進行的任務,例如將 container 註冊到服務發現系統 (`service discovery system`) 或監控工具。 * **`poststop`**:這個 `hook` 會在 container 的主要程序 (`primary process`) 退出或 container 被停止**後**執行。它可用於清理任務 (`cleanup tasks`)、記錄日誌 (`logging`) 或任何在 container 停止運行後應採取的行動。 `Container hooks` 可以在 container 的 `OCI` 設定檔中定義,該設定檔通常儲存為一個 `JSON` 檔案。此設定檔會指明 `hook` 腳本或指令的路徑,以及任何需要的參數 (`arguments`) 或環境變數 (`environment variables`)。 ## 快速動手實作 ### Step1: 設定 Podman `hook` 定義檔的存放位置 執行以下命令,編輯 `/etc/containers/containers.conf` 檔案: ``` sudo nano /etc/containers/containers.conf ``` 修改以下內容 : ``` # Path to OCI hooks directories for automatically executed hooks. # 將以下三行取消註解 hooks_dir = [ "/usr/share/containers/oci/hooks.d", ] ``` ### Step2: 以 Json 格式設定 Hook 定義檔 ``` sudo mkdir -p /usr/share/containers/oci/hooks.d/ sudo nano /usr/share/containers/oci/hooks.d/prestart-delay.json ``` 檔案內容如下 : ```json { "version": "1.0.0", "hook": { "path": "/usr/local/bin/delay.sh", }, "when": { "annotations": { "^delay$": ".+" } }, "stages": ["prestart"] } ``` ### Step3: 編輯 Hook 定義檔中宣告的 shell script,並賦予執行權限 ``` sudo nano /usr/local/bin/delay.sh ``` 檔案內容如下 : ``` #!/bin/bash set -x # 將 stderr 重新導向到一個日誌檔案以便除錯,同時也輸出到原始的 stderr exec 2> >(tee -a /var/log/oci-hooks.log >&2) # 從標準輸入 (stdin) 讀取容器狀態 JSON # OCI 執行階段會在 prestart 階段將此 JSON 傳遞給 Hook input="-" CONTAINER_CONFIG=$(cat "$input") # 檢查 jq 是否安裝 if ! command -v jq &> /dev/null; then echo "Error: jq is not installed. Cannot parse container state." >&2 exit 1 fi # 使用 jq 從 JSON 中解析我們自訂的註解值。 # 註解鍵為 "delay"。 # -r 選項移除引號。 # // "0" 提供一個預設值,如果註解不存在或為 null,則回傳 "0"。 delay_seconds=$(echo "$CONTAINER_CONFIG" | jq -r '.annotations["delay"] // "0"') # 輸入驗證:確保我們得到的是一個非負整數。 # 這可以防止錯誤或潛在的命令注入。 if ! [[ "$delay_seconds" =~ ^[0-9]+$ ]]; then echo "Warning: Invalid value for annotation delay: '$delay_seconds'. Must be a non-negative integer. Defaulting to 0." >&2 delay_seconds=0 fi # 如果延遲時間大於 0,則執行 sleep 並記錄日誌。 if [ "$delay_seconds" -gt 0 ]; then echo "Dynamic delay hook triggered. Sleeping for $delay_seconds seconds..." >&2 sleep "$delay_seconds" echo "Sleep complete. Container will now start." >&2 else # 如果延遲為 0 或無效,也記錄一條資訊,以便追蹤 Hook 是否被觸發。 echo "Dynamic delay hook triggered, but delay is 0. Starting container immediately." >&2 fi ``` 賦予程式執行權限 : ``` sudo chmod +x /usr/local/bin/delay.sh ``` ### Step4: 執行與驗證 #### 1. 先用 app container 驗證 ``` date; sudo podman run \ --rm \ -it \ --annotation delay=5 \ docker.io/library/alpine date ``` 執行結果 : ``` Sat Jul 26 16:41:05 CST 2025 Sat Jul 26 08:41:10 UTC 2025 ``` > 可以看到只差 5 秒 #### 2. 使用 podman pod 驗證 ``` # 建立 pod sudo podman pod create --name mypod # 建立 container c1,指定 annotation sudo podman create --name c1 --pod mypod \ --annotation delay=5 \ docker.io/library/alpine \ sh -c "date; sleep infinity" # 建立 container c2,指定 annotation sudo podman create --name c2 --pod mypod \ --annotation delay=10 \ docker.io/library/alpine \ sh -c "date; sleep infinity" # 建立 container c3,指定 annotation sudo podman create --name c3 --pod mypod \ --annotation delay=15 \ docker.io/library/alpine \ sh -c "date; sleep infinity" # 啟動所有 container sudo podman start c1 c2 c3 ``` 檢視 podman pod logs ``` $ sudo podman pod logs mypod ``` 執行結果 : ``` 9c922e6a8c15 Sat Jul 26 15:24:33 UTC 2025 caca4df50c11 Sat Jul 26 15:24:58 UTC 2025 5531bc974469 Sat Jul 26 15:24:43 UTC 2025 ```
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up