はじめに
こんにちは!新卒2年目 プラットフォームエンジニアリング部門 コンテナ基盤グループの開出です。
私たちコンテナ基盤グループは、アプリケーション開発者の皆さんがインフラ周りの複雑な設定に時間を割かれず、開発業務に集中できるようなプラットフォームを提供しています。
今回は私たちが直面したDocker Hubのレート制限という壁を、AWSの「Pull Through Cache」と「Repository Creation Template」という2つの強力な機能を組み合わせることで、課題を解決しつつより安定かつ効率的な基盤を構築した話をします。
見所は
- Docker Hubレート制限の回避とコスト削減
- イメージキャッシュによる安定運用と、AWS・Dockerアカウント双方でのコスト最適化
- クロスアカウントアクセスによる環境差分の解消
- 本番環境のECRを活用し、開発環境からのイメージプルを効率化する仕組み
- ECRの自動リポジトリ作成
- Pull Through CacheとRepository Creation Template連携によるリポジトリ管理の自動化と効率化
の3点です。
結論
私たちは、Docker Hubの有償アカウントを導入することでプルレート制限を解消し、ECRの「Pull Through Cache」機能と「Repository Creation Template」機能を組み合わせることで、この課題を解決しました。
本番環境のECRに開発環境からのクロスアカウントアクセスを可能にし、Docker Hubのレート制限を回避し、イメージをECRにキャッシュすることで、安定かつ効率的なイメージプルを実現することができました。
また、事前にECRリポジトリを作らずとも、イメージプルの段階で自動的に作成されることも大きな利点です。

背景
現状のEKSの運用において、私たちはDocker Hubの匿名アカウントを利用して(有償アカウントの設定をせずに)イメージプルを行っていました。しかし、この運用には大きな問題がありました。
それはDocker Hubからのイメージプルレート制限がいつ引き起こされるかわからないという問題です。
匿名アカウントの場合、6時間で100回のイメージプル制限がかかります(2025年7月時点)。
特に、マネージド Kubernetes の場合、イメージプルはクラスタの IP(NAT IP)アドレスを送信元としてリクエストされるため、同一の IP アドレスから大量の プルリクエストを送信すると、その IP に対して Docker Hub の Rate Limit が適用されます。 このため、単一の Pod が Rate Limit に引っかかると、他の Pod もイメージの取得ができなくなり、ImagePullBackOff や ErrImagePull に陥る可能性があります。
暫定的な対策として、Docker Hub以外のアップストリームレジストリ(GCRやQuayなど)からイメージをプルするように変更を進めていましたが、社内コンテナ基盤(EKS)を利用するアプリケーションが増えるにつれて現状が掴みづらくなっていました。加えて、一部にはDocker Hubからしかプルできないイメージも存在しており、これらのケースでDocker Hubへのイメージプルが頻繁に発生します。
頻繁に行われるDocker Hubへのイメージプルにより、一部のエコシステムや開発者が利用しているOSSのイメージプルに影響が出たり、コンテナの立ち上げ時間が増加、結果としてコスト増、最悪にはアプリケーションの起動ができなくなる可能性があります。
つまり、基盤全体に影響が及んでしまうという全環境停止のリスクを抱えていたのです。
イメージプルレート制限という課題はDocker Hubの有償アカウントを導入することで回避ができます。しかし、以下のような課題がまだ存在していました。
予測不能なイメージプルの発生と非効率な運用
予測不能なイメージプルの発生は、レート制限とは別の側面で運用上の課題となるため、有償アカウントを導入しても解決すべきだと考えました。
有償アカウントはDocker Hubからのイメージプルにおける回数制限がなくなりますが、イメージプルが「いつ」「どのくらい」発生するか、効率性、コスト、そして外部依存性(Docker Hub)に関する課題は残ります。具体的には Kubernetesリソース Deploymentのspecに
imagePullPolicy: IfNotPresent(ノード上に指定されたコンテナイメージがすでに存在しない場合にのみ、イメージレジストリからそのイメージプルをする)を設定していたとしても、新しいNodeが追加されたり、既存のNodeが入れ替わったりする際には、そのNodeにイメージがキャッシュされていないため、必ずイメージプルが発生します。また、イメージタグが
:latestである場合や、同じタグでもレジストリ側でイメージのダイジェスト(ハッシュ値)が変更された場合も、Kubernetesは最新のイメージを取得しようとします。これらの挙動により、予測不能なタイミングでDocker Hubへのアクセスが発生し、以下の問題を引き起こす可能性があります。- パフォーマンスとデプロイ速度への影響:
- 外部からのイメージプルには時間がかかり、アプリケーションのデプロイ速度やオートスケーリング時のコンテナ起動時間に遅延をもたらす可能性があります。
- 運用上のオーバーヘッド:
- 予測不能なトラフィック増、監視・トラブルシューティングの複雑化
- データ転送コストの増加:
- Docker Hubからのイメージプルには、AWSのデータ転送コスト(Outbound Data Transfer)が発生し、有償アカウントであってもこのコストは発生し続けます。
- パフォーマンスとデプロイ速度への影響:
複数アカウント環境におけるイメージ管理の複雑性と非効率性
私たちは複数のAWSアカウントでdev, stg, prodの各環境を運用しており、それぞれの環境でECR, Docker有償アカウントの設定を個別に行う必要がありました。
これにより、各環境で設定の重複が発生し、管理が複雑化するという課題がありました。
特に、ECRのレジストリURLが各環境固有のものになるため、アプリケーション開発者側でもKubernetesリソースDeploymentのイメージパスを環境ごとに変更する必要があり、運用が非効率でした。
解決方法
ECRの「Pull Through Cache」機能と「Repository Creation Template」機能を採用しました。
Pull Through Cacheについて
Pull Through Cacheは、ECRがアップストリームレジストリ(Docker Hubなど)からイメージを自動的にプルし、ECRリポジトリにキャッシュする機能です。
これにより、イメージプルリクエストがECRに直接送られるため、アップストリームレジストリのレート制限を回避し、イメージプルの速度を向上させることができます。
Repository Creation Templateについて
Repository Creation Templateは、ECRがPull Through Cacheによってリポジトリを自動作成する際に、あらかじめ定義されたポリシーを適用するための機能です。
これにより、新しいイメージがキャッシュされるたびに手動でリポジトリを作成したり、ポリシーを設定したりする手間を省き、管理を効率化することができます。クロスアカウントアクセスを許可するポリシーなども、このテンプレートで一元的に管理できます。
詳細
この章では、具体的な設定手順と導入における注意点について紹介します!
シークレット
今回はDocker有償アカウントの認証情報を用いてDocker Hubからのイメージプルを行います。そのため、認証情報を Secrets Managerのシークレットに保存する必要があります。
この際、ecr-pullthroughcache というプレフィックスを付けて保存しなければいけません。 このプレフィックスは、後述するPull Through Cacheの設定で参照されます。

ECRリポジトリの設定
本番環境(prod環境)のECRリポジトリにPull Through Cache設定を行います。
Pull Through Cacheの設定
Pull Through Cache設定では、以下の項目を指定します。 複数のイメージレジストリからイメージをプルする場合、それぞれのimageRegistryごとにPull Through Cacheの設定を行う必要があります。
resource "aws_ecr_pull_through_cache_rule" "ecr_pull_through_cache_rule" { ecr_repository_prefix = "docker-hub" upstream_registry_url = "registry-1.docker.io" credential_arn = "arn:aws:secretsmanager:ap-northeast-1:XXXXXXX:secret:ecr-pullthroughcache/dockerhub-credential-XXXX" }
ecr_repository_prefix:ECRリポジトリのプレフィックスを指定します。Secrets Managerに保存した認証情報のプレフィックスと一致させる必要があります。upstream_registry_url:アップストリームレジストリのURLを指定します。Docker Hubの場合はregistry-1.docker.ioとなります。
*credential_arn:Secrets Managerに保存した認証情報のARNを指定します。
Node Policyの設定
Nodeにアタッチするポリシーには、以下の権限を追加する必要があります。
これは、Pull Through CacheはアップストリームレジストリからイメージをプルしてECRにキャッシュする機能ですが、その前提としてECR内にイメージを格納するリポジトリが存在している必要があるためです。
これらの権限は、初回イメージプル時とそれ以降のイメージプル時の両方で、NodeがECRからイメージを適切に取得するために必要となります。
ecr:CreateRepository:ECRリポジトリを自動作成するための権限- Node(正確にはKubeletが動作するNodeのIAMロール)が新しいPodを起動しようとしたとき、そのPodが参照するイメージがECRにキャッシュされておらず、かつリポジトリ自体も存在しない場合があります。
- この時、NodeがECRに対してリポジトリ作成権限の要求を出す時に必要な権限です。
- Pull Through Cacheは「リポジトリが存在すればキャッシュする」機能ですが、「リポジトリをゼロから作成する」トリガーは、イメージプルを試みるクライアント(今回の場合はNode)からのリポジトリ作成要求に依存します。
ecr:BatchImportUpstreamImage:アップストリームレジストリからイメージをインポートするための権限- この権限は、ECRがアップストリームレジストリ(Docker Hub)からイメージをインポートする際に、Nodeがそのインポート処理を許可するために必要です。
- Nodeがイメージプルを要求し、その結果としてECRがDocker Hubからイメージをインポートしてキャッシュする際、このインポート操作自体にNodeからの権限が必要になります。
ecr:BatchGetImage: イメージのマニフェスト(メタデータ)を取得するための権限- この権限は、イメージをプルする際に、まずそのイメージのタグやダイジェスト、構成情報といったメタデータをECRから取得するために必要です。
- 初回イメージプル時も、キャッシュ済みイメージをプルする2回目以降も、この情報が必要となります。
ecr:GetDownloadUrlForLayer: イメージの各レイヤーのダウンロードURLを取得するための権限- コンテナイメージは複数のレイヤーで構成されており、実際にイメージをダウンロードする際には、これらのレイヤーごとにダウンロードURLを取得する必要があります。
- この権限は、ECRから個々のイメージレイヤーをダウンロードするために不可欠であり、初回イメージプル時と2回目以降のイメージプル時の両方で必要となります。
Terraformでの設定例は以下のようになります。
resource "aws_iam_policy" "node_policy" { name = "node-policy" description = "Policy for nodes to interact with ECR Pull Through Cache" policy = jsonencode({ Version = "2012-10-17", Statement = [ { Effect = "Allow", Action = [ "ecr:CreateRepository", "ecr:BatchImportUpstreamImage", "ecr:BatchGetImage", "ecr:GetDownloadUrlForLayer" ], Resource = "*" } ] }) } resource "aws_iam_role_policy_attachment" "node_policy_attachment" { role = aws_iam_role.node_role.name policy_arn = aws_iam_policy.node_policy.arn }
Repository Creation Templateの設定
次に、ECR Repository Creation Templateの設定を行います。
これは、Pull Through Cacheによって自動的に作成されるECRリポジトリに、あらかじめ決められたポリシーを適用するためのものです。
このRepository Creation Templateの設定をすることでクロスアカウントアクセスによるイメージプルが可能になります。
私たちは本番環境(prod環境) で一元的にECRリポジトリを運用しています。そのため、他アカウント からもリポジトリにアクセスできるよう、本番環境で作成されたリポジトリ自体に 適切なアクセス許可を設定する必要がありました。
テンプレート(ポリシー)を設定することで、Pull Through Cacheを利用して自動で作成されるリポジトリに対して、自動的に権限が付与されます。Principalにはクロスアカウントアクセスしたい各環境のnode-roleのARNを指定してください。
{ "Version": "2008-10-17", "Statement": [ { "Sid": "AllowPull", "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::XXXXXXXXXXXX:role/dev-node-role", "arn:aws:iam::XXXXXXXXXXXX:role/stg-node-role", "arn:aws:iam::XXXXXXXXXXXX:role/prod-node-role" ] }, "Action": [ "ecr:BatchGetImage", "ecr:GetDownloadUrlForLayer", "ecr:BatchImportUpstreamImage" ] } ] }
Terraformでの設定例です。
resource "aws_ecr_repository_creation_template" "ecr_pull_through_cache_repository_creation_template" { prefix = "docker-hub" description = "ecr-pull-through-cache-rule機能で動的に作成されたリポジトリに適用するテンプレート" image_tag_mutability = "IMMUTABLE" custom_role_arn = awscc_iam_role.ecr_template_role.arn applied_for = ["PULL_THROUGH_CACHE"] repository_policy = file("../policies/prod/ecr_repository_creation_template.json") lifecycle_policy = file("../policies/prod/ecr_pull_through_cache_lifecycle_policy.json") }
ECRテンプレートロールの設定
ECRテンプレートロールは、ECRサービスがRepository Creation Template の設定に基づいて、新しいECRリポジトリを自動的に作成し、そこに定義されたポリシー(リポジトリポリシーやライフサイクルポリシーなど)を適用するために必要です。
具体的には、以下の理由から ecr.amazonaws.com サービスプリンシパルへの AssumeRole 設定を行う必要があります。
- ECRサービスが代理で操作を行うため
- Pull Through Cache機能により、Docker Hubからイメージが初めてプルされ、ECR内にリポジトリが存在しない場合、ECRは自動的に新しいリポジトリを作成します。
- この「リポジトリの作成」や、そのリポジトリに「ポリシーを適用する」といった操作は、ユーザー(またはNodeのIAMロール)に代わってECRサービス自身が行います。この際、ECRサービスがこれらの操作を行うための権限を付与するために、ECRテンプレートロールが必要になります。
ecr.amazonaws.comはECRサービスの識別子ecr.amazonaws.comは、ECRサービス自体を識別するためのサービスプリンシパルです。- このサービスプリンシパルに
sts:AssumeRoleを許可することで、ECRサービスがこのロールを引き受けて、そのロールに付与された権限を使うことができます。
resource "awscc_iam_role" "ecr_template_role" { role_name = "ecr-repository-creation-template-service" assume_role_policy_document = jsonencode({ Version = "2012-10-17" Statement = [{ Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ecr.amazonaws.com" } }] }) }
イメージプルの詳細な挙動
初回イメージプル時の挙動
初回イメージプル時の挙動は以下のシーケンスで進行します。
- イメージプルリクエスト:
- NodeからECRサービスに対してイメージプルリクエストが発生します。
- 認証:
- Nodeが認証トークンを取得し、ECRサービスはクロスアカウントアクセスが許可されているか確認します。リポジトリが存在しない場合、Repository Creation Templateの権限設定を参照します。
- リポジトリ作成:
- ECRサービスは事前定義されたテンプレートに基づき、リポジリ作成ロールを引き受けて新規リポジトリを動的に作成します。
- リポジトリポリシー設定:
- 作成されたリポジリにポリシーが適用され、NodeのIAMロールに必要なアクセス権が付与されます。
- Docker Hubからのイメージ取得:
- ECRサービスは認証情報を取得し、Docker HubからイメージをインポートしてECRリポジトリにキャッシュとして保存します。この際、NodeのIAMロールに付与された
ecr:BatchImportUpstreamImage権限が使用されます。
- ECRサービスは認証情報を取得し、Docker HubからイメージをインポートしてECRリポジトリにキャッシュとして保存します。この際、NodeのIAMロールに付与された
- Nodeへの応答:
- ECRサービスは取得したイメージをNodeに提供します。

2回目以降のイメージプル時の挙動
- イメージプルリクエスト:
- NodeがECRからイメージをプルしようとします。
- 認証:
- ECRがプルリクエストを認証します。
- キャッシュ状態確認:
- ECRは要求されたイメージがキャッシュされているかを確認します。
- キャッシュイメージ提供:
- ECRはキャッシュされたイメージをNodeに提供します。

Kubernetes Deploymentにおけるイメージ指定と注意点
KubernetesリソースのDeploymentでコンテナイメージを指定する際には、spec.template.spec.containers.imageフィールドを使用します。Pull Through Cacheを設定している場合、Docker HubのイメージはECRを介してプルされるため、イメージパスはECRのレジストリURLを含む形式になります。
例えば、Docker Hubの公式イメージ(nginxなど)をPull Through Cache経由でプルする場合、通常は以下のように指定します。
apiVersion: apps/v1 kind: Deployment metadata: name: my-nginx-deployment spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: {aws_account_id}.dkr.ecr.{region}.amazonaws.com/docker-hub/library/nginx:latest ports: - containerPort: 80
Tips
⚠️ Docker Hubの公式イメージをPull Through Cache経由で取得する際は、必ずパスに library/ を含めてください。(例:{aws_account_id}.dkr.ecr.{region}.amazonaws.com/docker-hub/library/nginx:latest)
library/ を含めないと、ECRは docker-hub/image_name を探しに行きますが、公式イメージは docker-hub/library/image_name としてキャッシュされるため、イメージの取得に失敗します。
まとめと今後の展望
今回ご紹介したECRの「Pull Through Cache」と「Repository Creation Template」を組み合わせたイメージプル戦略では、Docker Hubのレート制限という課題を解決し、安定かつ効率的なイメージプルを実現しました。
この取り組みによって、Docker Hubのレート制限による全環境停止のリスクを回避し、コンテナの立ち上げ時間の短縮、そして結果としてコスト削減という大きな成果を得ることができました。 GKE環境においてもGAR Remote Repository機能を導入することで本記事と同様のことができるので気になる方はぜひ試してみてください。
今後の展望は、「Pod(コンテナ)の立ち上げ時間の定量的な比較」について、メトリクスを導入し、導入前後の効果をより詳細に分析したいと考えています。
今回の取り組みが、同じようなDocker Hubのレート制限やイメージプルに関する課題を抱えるチームや組織の参考になれば幸いです。そして、ECRの強力な機能を活用して、みなさんもより安定したプラットフォームづくりを進めていただければ嬉しいです!
当記事を通じてMonotaROに興味を持っていただいた方は、カジュアル面談もやっていますのでぜひご連絡ください。チームの採用募集も合わせてご覧ください。