本頁說明映像檔摘要,包括映像檔摘要的用途、如何尋找映像檔摘要,以及如何在 Kubernetes 叢集中強制使用映像檔摘要。本頁面適用於建構及部署容器映像的開發人員和作業人員。
容器映像檔摘要可不重複且不可變更地識別容器映像檔。使用摘要部署映像檔可避免使用映像檔標記部署映像檔的缺點。
本頁面的指令假設您可存取 Linux 或 macOS 的 Shell 環境,且已安裝 Google Cloud CLI、Docker、cURL、jq
和 pack
等工具。或者,您可以使用已預先安裝這些工具的 Cloud Shell。
容器映像檔和映像檔標記
使用容器映像檔時,您需要參照所用映像檔的方法。映像檔標記
是參照不同映像檔修訂版本的常見方式。常見的做法是在建構時為映像檔加上版本 ID。舉例來說,v1.0.1
可能是指您呼叫的 1.0.1
版本。
標記可讓使用者透過易讀字串輕鬆查閱圖片修訂版本。不過,標記是可變更的參照,因此標記參照的映像檔可能會變更,如下圖所示:
如上圖所示,如果您使用與現有映像檔相同的標記發布新映像檔,該標記會停止指向現有映像檔,並開始指向新映像檔。
圖片代碼的缺點
由於標記可變動,因此使用標記部署映像檔時,會有下列缺點:
在 Kubernetes 中,透過標記部署可能會導致非預期的結果。舉例來說,假設您有現有的 Deployment 資源,會依標記
v1.0.1
參照容器映像檔。如要修正錯誤或進行小幅變更,建構程序會建立具有相同標記v1.0.1
的新映像檔。即使您未變更 Deployment 資源規格,從 Deployment 資源建立的新 Pod 仍可能使用舊版或新版映像檔。這個問題也適用於其他 Kubernetes 資源,例如 StatefulSet、DaemonSet、ReplicaSet 和工作。如果您使用工具掃描或分析圖片,這些工具的結果只適用於掃描的圖片。為確保部署的是掃描的映像檔,您不能依賴標記,因為標記參照的映像檔可能已變更。
如果您搭配使用二進位授權和 Google Kubernetes Engine (GKE),系統會禁止以標記為基礎的部署作業,因為在建立 Pod 時,無法判斷使用的確切映像檔。
部署映像檔時,您可以使用映像檔摘要,避免使用標記的缺點。你還是可以視需要為圖片加上標記, 但不必這麼做。
圖片結構
映像檔包含下列元件:
下圖說明這些元件:
上圖顯示圖片元件的額外詳細資料:
- 圖片資訊清單是 JSON 文件,內含設定物件、檔案系統層和選用中繼資料的參照。
- 映像檔資訊清單會使用
digest
屬性,參照設定物件和每個檔案系統層。digest
屬性的值是摘要所指內容的密碼編譯雜湊,通常是使用 SHA-256 演算法計算。 - 摘要值用於建構物件的不變位址。這個程序稱為「可定址內容的儲存空間」,代表您可以根據摘要擷取映像檔資訊清單、映像檔索引、設定物件和層。
- 映像檔摘要是映像檔索引或映像檔資訊清單 JSON 文件的雜湊值。
- 設定物件是 JSON 文件,可定義映像檔的屬性,例如 CPU 架構、進入點、公開的連接埠和環境變數。
- 檔案系統層陣列會定義容器執行階段用來堆疊層的順序。這些層會以 tar 檔案的形式發布,通常會使用
gzip
公用程式壓縮。 - 選用的映像檔索引 (有時稱為資訊清單表) 會參照一或多個映像檔資訊清單。參考資料是映像檔資訊清單的摘要。如果您為不同平台 (例如
amd64
和arm64
架構) 製作多個相關圖片,映像檔索引就非常實用。
詳情請參閱「探索映像檔資訊清單、摘要和標記」一節。
尋找映像檔摘要
如要使用映像檔摘要進行部署,必須先找出摘要。接著,您可以在部署指令中使用摘要,或將摘要納入 Kubernetes 資訊清單。
視目前情況而定,您可以透過各種方式取得圖片摘要。以下各節包含不同產品和工具的範例。
在下列各節中,請在 Cloud Shell 或殼層環境中執行指令,並安裝 gcloud CLI、Docker、cURL 和 jq
等工具。
Artifact Registry
如要掃描儲存在 Artifact Registry 中的映像檔,請使用
gcloud artifacts docker images describe
指令。gcloud artifacts docker images describe \ LOCATION-docker.pkg.dev/PROJECT/REPOSITORY/IMAGE:TAG \ --format 'value(image_summary.digest)'
更改下列內容:
LOCATION
:存放區的區域或多區域位置PROJECT
:您的 Google Cloud 專案 IDREPOSITORY
:存放區名稱IMAGE
:圖片名稱TAG
:圖片代碼
Container Registry
如要取得儲存在 Container Registry 中的映像檔摘要,請提供名稱和標記,然後使用
gcloud container images describe
指令。使用--format
旗標,只顯示摘要:gcloud container images describe \ gcr.io/google-containers/pause-amd64:3.2 \ --format 'value(image_summary.digest)'
輸出內容大致如下,但摘要值可能有所不同:
sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
Cloud Build
如要取得使用 Cloud Build 建構的映像檔摘要,請使用 gcloud builds describe
指令搭配 --format
標記。無論您使用哪個登錄檔發布映像檔,這種做法都適用。
如要為已完成的建構作業執行這項操作,請按照下列步驟操作:
取得專案的建構版本清單:
gcloud builds list
請記下
BUILD_ID
。取得映像檔摘要:
gcloud builds describe BUILD_ID \ --format 'value(results.images[0].digest)'
將
BUILD_ID
替換為 Cloud Build 指派給建構作業的專屬 ID。
從目前專案的 Cloud Build 取得最新版本的映像檔名稱和摘要:
gcloud builds describe \ $(gcloud builds list --limit 1 --format 'value(id)') \ --format 'value[separator="@"](results.images[0].name,results.images[0].digest)'
如果建構作業產生多個映像檔,請篩選輸出內容,並取得其中一個映像檔的摘要:
gcloud builds describe BUILD_ID --format json \ | jq -r '.results.images[] | select(.name=="YOUR_IMAGE_NAME") | .digest'
將
YOUR_IMAGE_NAME
換成cloudbuild.yaml
檔案中的其中一個圖片名稱。如果您使用
gcloud builds submit
指令將建構作業提交至 Cloud Build,可以從輸出內容擷取映像檔摘要,並儲存在環境變數中:IMAGE_DIGEST=$(gcloud builds submit \ --format 'value(results.images[0].digest)' | tail -n1)
Cloud Native Buildpacks
如果您使用 Cloud Native Buildpacks 和 Google Cloud 建構子建構及發布映像檔,可以搭配
pack
指令使用--quiet
旗標擷取映像檔名稱和摘要:pack build --builder gcr.io/buildpacks/builder:v1 --publish --quiet \ LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE \ > image-with-digest.txt
更改下列內容:
LOCATION
:存放區的區域或多區域位置PROJECT_ID
:您的 Google Cloud 專案 IDREPOSITORY
:存放區名稱IMAGE
:圖片名稱
檔案
image-with-digest.txt
包含圖片名稱和摘要。如要為圖片新增標記,請使用
--tag
旗標。
Docker 用戶端
docker
指令列用戶端的manifest
子指令可從容器映像檔登錄檔擷取映像檔資訊清單和資訊清單清單。從映像檔
registry.k8s.io/pause:3.9
的資訊清單清單中取得摘要,適用於amd64
CPU 架構和linux
作業系統:docker manifest inspect --verbose registry.k8s.io/pause:3.9 | \ jq -r 'if type=="object" then .Descriptor.digest else .[] | select(.Descriptor.platform.architecture=="amd64" and .Descriptor.platform.os=="linux") | .Descriptor.digest end'
輸出看起來類似以下內容:
sha256:8d4106c88ec0bd28001e34c975d65175d994072d65341f62a8ab0754b0fafe10
如要取得儲存在本機 Docker Daemon 中,且已從映像檔登錄檔提取或推送至該登錄檔的映像檔摘要,請使用 Docker 指令列工具:
將映像檔拉取至本機 Docker Daemon:
docker pull docker.io/library/debian:bookworm
取得映像檔摘要:
docker inspect docker.io/library/debian:bookworm \ | jq -r '.[0].RepoDigests[0]' \ | cut -d'@' -f2
輸出內容會與以下所示內容類似,但摘要值可能不同:
sha256:3d868b5eb908155f3784317b3dda2941df87bbbbaa4608f84881de66d9bb297b
列出本機 Docker Daemon 中的所有映像檔和摘要:
docker images --digests
輸出會顯示具有摘要值的圖片摘要。只有從映像檔登錄檔提取或推送至該登錄檔的映像檔,才會有摘要值。
crane
和 gcrane
您可以使用開放原始碼的 crane
和 gcrane
指令列工具,取得映像檔的摘要,而不必將映像檔提取至本機 Docker 精靈。
將
crane
和gcrane
下載至目前目錄:VERSION=$(curl -sL https://api.github.com/repos/google/go-containerregistry/releases/latest | jq -r .tag_name) curl -L "https://github.com/google/go-containerregistry/releases/download/${VERSION}/go-containerregistry_$(uname -s)_$(uname -m).tar.gz" | tar -zxf - crane gcrane
取得圖片摘要:
./gcrane digest gcr.io/distroless/static-debian11:nonroot
crane
和gcrane
還有其他功能,不在本頁面的討論範圍內。詳情請參閱crane
和gcrane
的說明文件。
在 Kubernetes 部署作業中強制使用映像檔摘要
如要強制對部署至 Kubernetes 叢集的映像檔使用摘要,可以採用 Policy Controller 或 Open Policy Agent (OPA) Gatekeeper。Policy Controller 是以 OPA Gatekeeper 開放原始碼專案為基礎建構而成。
Policy Controller 和 OPA Gatekeeper 都是以 OPA 政策引擎為基礎。Policy Controller 和 OPA Gatekeeper 提供 Kubernetes 驗證許可控制器 Webhook,可強制執行政策,並提供自訂資源定義 (CRD),用於限制範本和限制。
限制範本包含以高階宣告式語言 (稱為 Rego) 表示的政策邏輯。以下是驗證容器、init 容器和臨時容器的限制範本,確保 Kubernetes 資源規格中的這些容器使用含有摘要的映像檔:
上述政策包含規則運算式,做為 re_match
函式的輸入內容。這個規則運算式會比對容器映像檔摘要,並以開放容器倡議映像檔規格中的摘要格式為依據。
限制會比對 kind
和 namespace
等屬性,將政策套用至 Kubernetes 資源。以下範例限制會將限制範本中的政策套用至 default
命名空間中的所有 Pod
資源。
建立限制範本和限制後,default
名稱空間中的任何新 Pod 都必須使用映像檔摘要,才能參照容器映像檔。
如需完整範例,請參閱 Gatekeeper 政策程式庫中的imagedigests
政策。
關於映像檔資訊清單、摘要和標記
在本節中,您將瞭解如何使用 curl
和 docker
等指令列工具,探索登錄檔中的現有映像檔。在 Cloud Shell 中執行指令,或在已安裝 gcloud CLI、Docker、cURL 和 jq
等工具的殼層環境中執行指令。下列指令會使用 Artifact Registry 中的公開映像檔。
使用 cURL 和資訊清單網址取得圖片的資訊清單
gcr.io/google-containers/pause-amd64:3.2
:curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2
輸出結果會與下列內容相似:
{ "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "config": { "mediaType": "application/vnd.docker.container.image.v1+json", "size": 759, "digest": "sha256:80d28bedfe5dec59da9ebf8e6260224ac9008ab5c11dbbe16ee3ba3e4439ac2c" }, "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 296534, "digest": "sha256:c74f8866df097496217c9f15efe8f8d3db05d19d678a02d01cc7eaed520bb136" } ] }
config
區段具有摘要屬性,您可以使用這個值擷取設定物件。同樣地,每個層都有digest
屬性,可用於擷取該層的 tar 檔案。如果圖片包含選用的圖片索引,使用標記對資訊清單網址發出的 HTTP
GET
要求,會傳回圖片索引,而不是圖片資訊清單。取得圖片
gcr.io/google-containers/pause:3.2
的圖片索引:curl -s https://gcr.io/v2/google-containers/pause/manifests/3.2
輸出結果會與下列內容相似:
{ "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json", "manifests": [ { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 526, "digest": "sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108", "platform": { "architecture": "amd64", "os": "linux" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 526, "digest": "sha256:bbb7780ca6592cfc98e601f2a5e94bbf748a232f9116518643905aa30fc01642", "platform": { "architecture": "arm", "os": "linux", "variant": "v7" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 526, "digest": "sha256:31d3efd12022ffeffb3146bc10ae8beb890c80ed2f07363515580add7ed47636", "platform": { "architecture": "arm64", "os": "linux" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 526, "digest": "sha256:7f82fecd72730a6aeb70713476fb6f7545ed1bbf32cadd7414a77d25e235aaca", "platform": { "architecture": "ppc64le", "os": "linux" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 526, "digest": "sha256:1175fd4d728641115e2802be80abab108b8d9306442ce35425a4e8707ca60521", "platform": { "architecture": "s390x", "os": "linux" } } ] }
篩選結果,擷取所需平台的圖片摘要。取得
amd64
CPU 架構和linux
作業系統的映像檔資訊清單摘要:curl -s https://gcr.io/v2/google-containers/pause/manifests/3.2 | \ jq -r '.manifests[] | select(.platform.architecture=="amd64" and .platform.os=="linux") | .digest'
這項指令中的篩選作業會模擬容器執行階段 (例如 containerd) 從映像檔索引選取符合目標平台的映像檔。
輸出結果會與下列內容相似:
sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
取得圖片的摘要
gcr.io/google-containers/pause-amd64:3.2
:curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | shasum -a 256 \ | cut -d' ' -f1
輸出結果會與下列內容相似:
4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
您可以使用映像檔摘要值參照這個映像檔,如下所示:
gcr.io/google-containers/pause-amd64@sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
使用內容可定址儲存空間概念,以摘要做為參照,取得映像檔資訊清單:
curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
許多容器映像檔登錄檔會在回應 HTTP
HEAD
要求時,於Docker-Content-Digest
標頭中傳回資訊清單、映像檔索引、設定物件和檔案系統層的摘要。取得圖片索引的摘要,圖片索引是指圖片的摘要:gcr.io/google-containers/pause-amd64:3.2
curl -s --head https://gcr.io/v2/google-containers/pause/manifests/3.2 \ | grep -i Docker-Content-Digest \ | cut -d' ' -f2
輸出結果會與下列內容相似:
sha256:927d98197ec1141a368550822d18fa1c60bdae27b78b0c004f705f548c07814f
Docker-Content-Digest
標頭並非 Open Container Initiative Distribution 規格的必要項目,因此這個方法可能不適用於所有容器映像檔登錄檔。您可以搭配 Artifact Registry 和 Container Registry 使用。如要使用映像檔資訊清單中的摘要值擷取映像檔設定物件,請執行下列操作:
取得設定摘要:
CONFIG_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | jq -r '.config.digest')
使用設定摘要擷取設定物件,並使用
jq
格式化輸出內容,方便閱讀:curl -sL https://gcr.io/v2/google-containers/pause-amd64/blobs/$CONFIG_DIGEST \ | jq
輸出結果會與下列內容相似:
{ "architecture": "amd64", "config": { "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Entrypoint": [ "/pause" ], "WorkingDir": "/", "OnBuild": null }, "created": "2020-02-14T10:51:50.60182885-08:00", "history": [ { "created": "2020-02-14T10:51:50.60182885-08:00", "created_by": "ARG ARCH", "comment": "buildkit.dockerfile.v0", "empty_layer": true }, { "created": "2020-02-14T10:51:50.60182885-08:00", "created_by": "ADD bin/pause-amd64 /pause # buildkit", "comment": "buildkit.dockerfile.v0" }, { "created": "2020-02-14T10:51:50.60182885-08:00", "created_by": "ENTRYPOINT [\"/pause\"]", "comment": "buildkit.dockerfile.v0", "empty_layer": true } ], "os": "linux", "rootfs": { "type": "layers", "diff_ids": [ "sha256:ba0dae6243cc9fa2890df40a625721fdbea5c94ca6da897acdd814d710149770" ] } }
如要使用映像檔資訊清單中的摘要值擷取檔案系統層,請按照下列步驟操作:
取得要擷取圖層的摘要:
LAYER_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | jq -r '.layers[0].digest')
使用層摘要擷取層 tar 檔案,並列出內容:
curl -sL https://gcr.io/v2/google-containers/pause-amd64/blobs/$LAYER_DIGEST \ | tar --list
這個圖層只有一個名為
pause
的檔案。
如要查詢與映像檔摘要相關聯的標記,請按照下列步驟操作:
定義要查詢的摘要:
IMAGE_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \ | shasum -a 256 \ | cut -d' ' -f1)
IMAGE_DIGEST
環境變數包含標記3.2
參照的映像檔摘要。使用映像檔標記清單端點
/tags/list
列出標記資訊,並擷取摘要值的標記:curl -s "https://gcr.io/v2/google-containers/pause-amd64/tags/list?n=1" \ | jq ".manifest.\"sha256:$IMAGE_DIGEST\".tag"
輸出結果會與下列內容相似:
[ "3.2" ]
如要使用 cURL 從 Artifact Registry 容器映像檔存放區取得映像檔資訊清單,請在
Authorization
要求標頭中加入存取權杖:curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \ https://LOCATION-docker.pkg.dev/v2/PROJECT_ID/REPOSITORY/IMAGE/manifests/DIGEST
更改下列內容:
LOCATION
:存放區的區域或多區域位置PROJECT_ID
:您的 Google Cloud 專案 IDREPOSITORY
:存放區名稱IMAGE
:圖片名稱DIGEST
:圖片摘要,格式為sha256:DIGEST_VALUE