如何解決 Amazon ECS 中的「CannotPullContainerError:您已達到提取速率限制」錯誤?

上次更新日期:2022 年 3 月 25 日

當我嘗試從 Docker Hub 提取映像時,我的 Amazon Elastic Container Service (Amazon ECS) 任務失敗並給出以下錯誤:

CannotPullContainerError:檢查映像已重試 5 次:httpReaderSeeker:開啟失敗:意外狀態代碼 https://registry-1.docker.io/v2/manifests/sha256:2bb501e6429 太多請求 - 伺服器訊息:toomanyrequests:您已達到提取速率限制。您可以透過身分驗證和升級來增加限制:https://www.docker.com/increase-rate-limit

簡短描述

當您在達到 Docker 提取速率限制之後嘗試從公有 Docker Hub 儲存庫中提取映像時,就會得到此錯誤,同時傳回 429 的 HTTP 狀態碼。Docker Hub 使用 IP 地址對使用者進行身分驗證,而提取速率限制基於各個 IP 地址。對於匿名使用者,速率限制設定為每個 IP 地址每 6 小時 100 次提取。對於具有 Docker ID 且經過身分驗證的使用者,提取速率設定為每 6 小時 200 次提取。如果您的映像提取請求超過這些限制,這些請求將被拒絕,直到經過 6 小時時段才會再次允許。如果您正在執行 Amazon ECS/Amazon EKS 工作負載,則大多數資料將透過具有固定 IP 地址的 NAT Gateway 提取。在此情況下,當您超過提取限制時,請求會受到調節。

解決方案

使用下列解決方法之一來排查此問題。

將公有映像複製到 Amazon ECR 私有註冊表中

建立 Amazon Elastic Container Registry (Amazon ECR) 儲存庫,然後將映像推送到此新儲存庫中。藉助這種方法,您可以透過從 Amazon ECR 儲存庫中提取映像來避免超出 Docker Hub 提取限制。

1.    執行類似於以下的命令,從 Docker Hub 中提取映像:

docker pull example-image

2.    運行類似於以下的命令,對 Docker 用戶端進行身分驗證,以存取 Amazon ECR 註冊表:

aws ecr get-login-password --region eu-west-1 | docker login --username AWS --password-stdin 1111222233334444.dkr.ecr.eu-west-1.amazonaws.com

3.    運行類似於以下的命令,標記要推送到儲存庫的映像:

docker tag myrepository:latest 1111222233334444.dkr.ecr.eu-west-1.amazonaws.com/myrepository:latest

4.    運行類似於以下的命令,將 Docker 映像推送到 Amazon ECR 註冊表:

docker push 1111222233334444.dkr.ecr.eu-west-1.amazonaws.com/myrepository:latest

5.    運行類似於以下的命令,將 Docker 檔案更新為使用新推送的 Amazon ECR 映像作為基礎映像:

FROM 1111222233334444.dkr.ecr.eu-west-1.amazonaws.com/myrepository:tag

請務必取代上述命令中的下列值:

  • example-image 取代為要推送的公有映像的名稱
  • 1111222233334444 取代為您的帳戶 ID
  • myrepository:latest 取代為您的 Amazon ECR 註冊表名稱
  • eu-west-1 取代為您選擇的區域

對 Docker Hub 提取進行身分驗證

如果您對 Docker Hub 進行身分驗證,則作為經過身分驗證的使用者,您將有更多的速率限制,並且根據 Docker 使用者名稱進行速率限制。您可以將 Docker Hub 使用者名稱和密碼作為密碼儲存在 AWS Secrets Manager 中,然後使用此密碼對 Docker Hub 進行身分驗證。

為 Docker Hub 憑證建立 Secrets Manager 密碼

若要為 Docker Hub 憑證建立密碼,請使用啟用私有註冊表身分驗證建立基本密碼區段下的説明。

更新您的任務執行 AWS Identity and Access Management (AWS IAM) 角色

要將 Amazon ECS 任務的存取許可授予您建立的密碼,必須手動將所需許可作為內嵌政策新增至任務執行角色。

1.    開啟 IAM 主控台

2.    在導覽窗格中,選擇 Roles (角色)

3.    搜尋 ecsTaskExecutionRole 的角色清單,然後選擇要檢視已連接政策的角色。

4.    在許可索引標籤上,選擇新增許可,然後選擇建立內嵌政策

5.    在新增政策頁面中,選擇 JSON,然後複製並貼入以下政策:

{
 "Version": "2012-10-17",
 "Statement": [{
  "Effect": "Allow",
  "Action": [
   "secretsmanager:GetSecretValue",
   "kms:Decrypt"
  ],
  "Resource": [
   "arn:aws:secretsmanager:eu-west-1:1111222233334444:secret:dockerhub-0knT",
   "arn:aws:kms:eu-west-1:1111222233334444:key/mykey"
  ]
 }]
}

務必取代政策中的以下內容:

  • 1111222233334444 取代為您的帳戶 ID
  • eu-west-1 取代為您選擇的區域
  • mykey 取代為您的 AWS KMS 金鑰

注意: 僅當您的金鑰未使用預設金鑰且使用自訂 AWS Key Management Service (AWS KMS) 金鑰時,才包含 kms:Decrypt。將自訂金鑰的 ARN 作為資源新增。

6.    選擇 Review policy(檢閱政策)。

7.    對於名稱,輸入政策名稱 (ECSSecrets)。

8.    選擇建立政策

建立使用 Docker 身分驗證密碼的任務定義

按照使用傳統主控台建立任務定義中的説明建立您的 Amazon ECS 任務定義。對於任務執行角色,請確保選擇在上一區段中更新的任務執行 IAM 角色。

容器定義區段中,執行以下操作:

  1. 選擇新增容器
  2. 對於容器名稱,輸入容器的名稱。
  3. 對於映像,輸入映像的名稱,或者包括私有映像的路徑 (範例:repository-url/image.tag)。
  4. 選擇私有儲存庫身分驗證
  5. 對於 Secrets Manager ARN 或名稱,輸入您建立的密碼的 ARN。
  6. 選擇新增

建立 Amazon ECS 叢集並執行 Amazon ECS 任務

建立 Amazon ECS 叢集。然後,使用在前一區段中建立的任務定義執行任務

將 Amazon ECR 公有註冊表用於公有容器映像

標識您在 Docker 檔案中使用的公有映像。使用適當的搜尋篩選條件在 Amazon ECR 公有庫中搜尋這些映像。您無需進行身分驗證即可瀏覽公有儲存庫和提取映像。Amazon ECR 公有註冊表包含流行的基礎映像,包括作業系統、AWS 發佈的映像、Kubernetes 附加元件和成品。您可以透過從 Amazon ECR 公有註冊表中提取映像來避免達到 Docker Hub 的速率限制。

您可以將這些映像用作任務定義中容器映像的來源:

ContainerDefinitions: [
 {
 ...
 Image: 'public.ecr.aws/cloudwatch-agent/cloudwatch-agent:latest'
 ...
 }
 ]

您還可以選擇將這些映像用作 Docker 檔案中的基礎映像:

Docker File
FROM public.ecr.aws/amazonlinux/amazonlinux:latest

升級到 Docker Pro 或 Team 訂閲

您可以將計劃升級到 Docker ProTeam 訂閲,該訂閲可在 24 小時內提供 50,000 次提取。有關定價計劃的詳細資訊,請參閲 Docker Hub 定價


此文章是否有幫助?


您是否需要帳單或技術支援?