本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
遷移至 Amazon ECR 儲存庫時,自動識別重複的容器映像
由 Rishabh Yadav (AWS) 和 Rishi Singla (AWS) 建立
Summary
注意: AWS CodeCommit 不再提供給新客戶。的現有客戶 AWS CodeCommit 可以繼續正常使用服務。進一步了解
此模式提供自動化解決方案,以識別存放在不同容器儲存庫中的映像是否為重複。當您計劃將映像從其他容器儲存庫遷移到 Amazon Elastic Container Registry (Amazon ECR) 時,此檢查很有用。
如需基礎資訊,模式也會說明容器映像的元件,例如映像摘要、資訊清單和標籤。當您計劃遷移至 Amazon ECR 時,您可以比較映像摘要,以決定跨容器登錄檔同步容器映像。遷移容器映像之前,您需要檢查 Amazon ECR 儲存庫中是否已存在這些映像,以防止重複。不過,比較映像摘要可能很難偵測重複,這可能會導致初始遷移階段的問題。 此模式會比較存放在不同容器登錄檔中的兩個類似影像的摘要,並說明摘要為何不同,以協助您準確比較影像。
先決條件和限制
作用中 AWS 帳戶
存取 Amazon ECR 公有登錄
檔 熟悉下列項目 AWS 服務:
設定的 CodeCommit 登入資料 (請參閱指示)
架構
容器映像元件
下圖說明容器映像的一些元件。這些元件會在圖表後說明。

術語和定義
下列詞彙在開放容器計劃 (OCI) 影像規格
登錄檔:映像儲存和管理的服務。
用戶端:與 登錄檔通訊並搭配本機映像使用的工具。
推送:將映像上傳至登錄檔的程序。
提取:從登錄檔下載映像的程序。
Blob:由登錄檔存放且可由摘要處理之內容的二進位形式。
索引:識別不同電腦平台 (例如 x86-64 或 ARM 64 位元) 或媒體類型的多個影像清單的建構。如需詳細資訊,請參閱 OCI 影像索引規格
。 資訊清單:定義透過資訊清單端點上傳之影像或成品的 JSON 文件。資訊清單可以使用描述項來參考儲存庫中的其他 Blob。如需詳細資訊,請參閱 OCI Image Manifest 規格
。 檔案系統層:系統程式庫和其他映像的相依性。
組態:包含成品中繼資料並在資訊清單中參考的 Blob。如需詳細資訊,請參閱 OCI Image Configuration Specification
。 物件或成品:存放在 Blob 中的概念內容項目,並與具有組態的隨附資訊清單相關聯。
摘要:從資訊清單內容的密碼編譯雜湊建立的唯一識別符。映像摘要有助於唯一識別不可變的容器映像。當您使用映像摘要提取映像時,每次在任何作業系統或架構上都會下載相同的映像。如需詳細資訊,請參閱 OCI Image Specification
。 標籤:人類可讀取的資訊清單識別符。相較於不可變的影像摘要,標籤是動態的。指向影像的標籤可以變更,並從一個影像移動到另一個影像,但基礎影像摘要保持不變。
目標架構
下圖顯示此模式所提供解決方案的高階架構,透過比較存放在 Amazon ECR 和私有儲存庫中的映像來識別重複的容器映像。

工具
AWS 服務
AWS CloudFormation 可協助您設定 AWS 資源、快速且一致地佈建資源,以及在整個 AWS 帳戶 和 區域的生命週期中管理資源。
AWS CodeBuild是一種全受管建置服務,可協助您編譯原始程式碼、執行單位測試,並產生準備好部署的成品。
AWS CodeCommit 是一種版本控制服務,可協助您私下存放和管理 Git 儲存庫,而無需管理您自己的來源控制系統。
AWS CodePipeline 可協助您快速建模和設定軟體版本的不同階段,並自動化持續發行軟體變更所需的步驟。
Amazon Elastic Container Registry (Amazon ECR) 是一種受管容器映像登錄服務,安全、可擴展且可靠。
程式碼
此模式的程式碼可在 GitHub 儲存庫中取得 自動解決方案,以識別儲存庫之間的重複容器映像
最佳實務
史詩
任務 | 描述 | 所需的技能 |
---|---|---|
從 Amazon ECR 公有儲存庫中提取映像。 | 從終端機執行下列命令,
將映像提取至本機機器後,您會看到下列提取摘要,其代表映像索引。
| 應用程式開發人員、AWS DevOps、AWS 管理員 |
將映像推送至 Amazon ECR 私有儲存庫。 |
| AWS 管理員、AWS DevOps、應用程式開發人員 |
從 Amazon ECR 私有儲存庫中提取相同的映像。 |
| 應用程式開發人員、AWS DevOps、AWS 管理員 |
任務 | 描述 | 所需的技能 |
---|---|---|
尋找存放在 Amazon ECR 公有儲存庫中的映像資訊清單。 | 從終端機執行下列命令,
| AWS 管理員、AWS DevOps、應用程式開發人員 |
尋找存放在 Amazon ECR 私有儲存庫中的映像資訊清單。 | 從終端機執行下列命令,
| AWS DevOps、AWS 系統管理員、應用程式開發人員 |
比較 Docker 提取的摘要與 Amazon ECR 私有儲存庫中映像的資訊清單摘要。 | 另一個問題是為什麼 docker pull 命令提供的摘要與影像 的資訊清單摘要不同 用於 docker pull 的摘要代表影像資訊清單的摘要,存放在登錄檔中。此摘要被視為雜湊鏈的根目錄,因為資訊清單包含將下載並匯入 Docker 的內容雜湊。 Docker 中使用的映像 ID 可在此資訊清單中找到,名稱為 若要確認此資訊,您可以比較 Amazon ECR 公有和私有儲存庫上 docker inspect 命令的輸出: 結果會驗證兩個影像具有相同的影像 ID 摘要和圖層摘要。 ID: 圖層: 此外,摘要是根據本機受管物件的位元組 (本機檔案是容器映像層的 tar) 或推送至登錄伺服器的 Blob。不過,當您將 Blob 推送至登錄檔時,會壓縮 tar,並在壓縮的 tar 檔案中計算摘要。因此,Docker 提取摘要值的差異來自套用至登錄檔 (Amazon ECR 私有或公有) 層級的壓縮。 注意此說明專屬於使用 Docker 用戶端。您不會在其他用戶端看到此行為,例如 nerdctl 或 Finch,因為它們不會在推送和提取操作期間自動壓縮映像。 | AWS DevOps、AWS 系統管理員、應用程式開發人員 |
任務 | 描述 | 所需的技能 |
---|---|---|
複製儲存庫。 | 將此模式的 Github 儲存庫複製到本機資料夾:
| AWS 管理員、AWS DevOps |
設定 CI/CD 管道。 | GitHub 儲存庫包含一個
管道將設定兩個階段 (CodeCommit 和 CodeBuild,如架構圖表所示),以識別私有儲存庫中也存在於公有儲存庫中的映像。管道使用下列資源設定:
| AWS 管理員、AWS DevOps |
填入 CodeCommit 儲存庫。 | 若要填入 CodeCommit 儲存庫,請執行下列步驟:
| AWS 管理員、AWS DevOps |
清除。 | 若要避免產生未來的費用,請依照下列步驟刪除資源:
| AWS 管理員 |
故障診斷
問題 | 解決方案 |
---|---|
當您嘗試從終端機或命令列推送、提取或以其他方式與 CodeCommit 儲存庫互動時,系統會提示您提供使用者名稱和密碼,而且您必須為 IAM 使用者提供 Git 憑證。 | 此錯誤最常見的原因如下:
根據作業系統和本機環境,您可能需要安裝登入資料管理工具、設定作業系統中包含的登入資料管理工具,或自訂本機環境以使用登入資料儲存體。例如,如果您的電腦正在執行 macOS,您可以使用 Keychain Access 公用程式來存放您的登入資料。如果您的電腦執行 Windows,您可以使用隨著適用於 Windows 的 Git 安裝的 Credential Manager。如需詳細資訊,請參閱 CodeCommit 文件中的使用 Git 登入資料為 HTTPS 使用者設定,以及 Git 文件中的登入資料儲存 |
當您將映像推送到 Amazon ECR 儲存庫時,遇到 HTTP 403 或「沒有基本身分驗證登入資料」錯誤。 | 即使您已成功使用 aws ecr get-login-password 命令向 Docker 驗證身分,您仍可能會遇到來自 docker push 或 docker pull 命令的這些錯誤訊息。已知原因包括: |
相關資源
自動化解決方案,以識別儲存庫之間的重複容器映像
(GitHub 儲存庫) Amazon ECR 中的私有映像 (Amazon ECR 文件)
AWS::CodePipeline::Pipeline 資源 (AWS CloudFormation 文件)
其他資訊
Amazon ECR 公有儲存庫中映像的 Docker 檢查輸出
[
{
"Id": "sha256:f7cee5e1af28ad4e147589c474d399b12d9b551ef4c3e11e02d982fce5eebc68",
"RepoTags": [
"<account-id>.dkr.ecr.us-east-1.amazonaws.com/test_ecr_repository:latest",
"public.ecr.aws/amazonlinux/amazonlinux:2018.03"
],
"RepoDigests": [
"<account-id>.dkr.ecr.us-east-1.amazonaws.com/test_ecr_repository@sha256:52db9000073d93b9bdee6a7246a68c35a741aaade05a8f4febba0bf795cdac02",
"public.ecr.aws/amazonlinux/amazonlinux@sha256:f972d24199508c52de7ad37a298bda35d8a1bd7df158149b381c03f6c6e363b5"
],
"Parent": "",
"Comment": "",
"Created": "2023-02-23T06:20:11.575053226Z",
"Container": "ec7f2fc7d2b6a382384061247ef603e7d647d65f5cd4fa397a3ccbba9278367c",
"ContainerConfig": {
"Hostname": "ec7f2fc7d2b6",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"/bin/bash\"]"
],
"Image": "sha256:c1bced1b5a65681e1e0e52d0a6ad17aaf76606149492ca0bf519a466ecb21e51",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"DockerVersion": "20.10.17",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/bash"
],
"Image": "sha256:c1bced1b5a65681e1e0e52d0a6ad17aaf76606149492ca0bf519a466ecb21e51",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 167436755,
"VirtualSize": 167436755,
"GraphDriver": {
"Data": {
"MergedDir": "/var/lib/docker/overlay2/c2c2351a82b26cbdf7782507500e5adb5c2b3a2875bdbba79788a4b27cd6a913/merged",
"UpperDir": "/var/lib/docker/overlay2/c2c2351a82b26cbdf7782507500e5adb5c2b3a2875bdbba79788a4b27cd6a913/diff",
"WorkDir": "/var/lib/docker/overlay2/c2c2351a82b26cbdf7782507500e5adb5c2b3a2875bdbba79788a4b27cd6a913/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:d5655967c2c4e8d68f8ec7cf753218938669e6c16ac1324303c073c736a2e2a2"
]
},
"Metadata": {
"LastTagTime": "2023-03-02T10:28:47.142155987Z"
}
}
]
Amazon ECR 私有儲存庫中映像的 Docker 檢查輸出
[
{
"Id": "sha256:f7cee5e1af28ad4e147589c474d399b12d9b551ef4c3e11e02d982fce5eebc68",
"RepoTags": [
"<account-id>.dkr.ecr.us-east-1.amazonaws.com/test_ecr_repository:latest",
"public.ecr.aws/amazonlinux/amazonlinux:2018.03"
],
"RepoDigests": [
"<account-id>.dkr.ecr.us-east-1.amazonaws.com/test_ecr_repository@sha256:52db9000073d93b9bdee6a7246a68c35a741aaade05a8f4febba0bf795cdac02",
"public.ecr.aws/amazonlinux/amazonlinux@sha256:f972d24199508c52de7ad37a298bda35d8a1bd7df158149b381c03f6c6e363b5"
],
"Parent": "",
"Comment": "",
"Created": "2023-02-23T06:20:11.575053226Z",
"Container": "ec7f2fc7d2b6a382384061247ef603e7d647d65f5cd4fa397a3ccbba9278367c",
"ContainerConfig": {
"Hostname": "ec7f2fc7d2b6",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"/bin/bash\"]"
],
"Image": "sha256:c1bced1b5a65681e1e0e52d0a6ad17aaf76606149492ca0bf519a466ecb21e51",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"DockerVersion": "20.10.17",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/bash"
],
"Image": "sha256:c1bced1b5a65681e1e0e52d0a6ad17aaf76606149492ca0bf519a466ecb21e51",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 167436755,
"VirtualSize": 167436755,
"GraphDriver": {
"Data": {
"MergedDir": "/var/lib/docker/overlay2/c2c2351a82b26cbdf7782507500e5adb5c2b3a2875bdbba79788a4b27cd6a913/merged",
"UpperDir": "/var/lib/docker/overlay2/c2c2351a82b26cbdf7782507500e5adb5c2b3a2875bdbba79788a4b27cd6a913/diff",
"WorkDir": "/var/lib/docker/overlay2/c2c2351a82b26cbdf7782507500e5adb5c2b3a2875bdbba79788a4b27cd6a913/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:d5655967c2c4e8d68f8ec7cf753218938669e6c16ac1324303c073c736a2e2a2"
]
},
"Metadata": {
"LastTagTime": "2023-03-02T10:28:47.142155987Z"
}
}
]