Amazon ECRのコンテナイメージを更新した一方でAmazon ECSのサービスを更新しなかった場合、タスク定義の設定によっては新規タスク起動時にCannotPullContainerErrorで失敗する

Amazon ECRのコンテナイメージを更新した一方でAmazon ECSのサービスを更新しなかった場合、タスク定義の設定によっては新規タスク起動時にCannotPullContainerErrorで失敗する

Amazon ECSタスクの起動時に、Amazon ECSタスク定義から参照しているAmazon ECRのコンテナイメージがARN同じのまま更新されていたら、CannotPullContainerErrorが発生することがあります。特にコンテナイメージをlatest運用している場合はハマってしまうかもしれません。
Clock Icon2025.04.21

CannotPullContainerErrorでAmazon ECS新規タスク起動に失敗する

おのやんです。

みなさん、Amazon ECS(以下、ECS)が新規タスクを起動しようとしたときに、CannotPullContainerErrorで新規タスク起動に失敗したことはありますか?私はあります。

原因はタイトルの通りで、 Amazon ECR(以下、ECR)のコンテナイメージを更新した一方でECSのサービスを更新しないため なのですが、ネットの検索でも意外と引っかからなかったので、ブログに情報をまとめてみます。

前提条件

今回のECSの環境情報は以下の通りです。過去のさまざまな要件を経て、このような運用に落ち着いています。

  • 1つのECSサービスで、1つのECSタスクを管理している
  • ECSサービスのDesiredCountは1に設定している
  • 頻繁なタスク定義更新は控える
  • タスク定義で参照するECRイメージのタグは、常に001
  • ECRにコンテナイメージをプッシュする場合は、最新のコンテナイメージに001のタグをつけている(いわゆるlatest運用)
  • CI/CDでコンテナイメージpushとAWS Serverless Application Model (SAM) デプロイを自動化している
  • ECSサービスの更新は、手動で実行している

CannotPullContainerErrorが発生した経緯

開発環境で作業を行う際は、コードリポジトリにGitのコミットをプッシュしてでCI/CDを実行しています。この際、コンテナイメージビルド & pushは必ず実行されるようになっていました。そのため、ECSで実行されるプログラム内容が同じであってもECR上のコンテナイメージはコミットがpushされるたびに別のものになっていました。コードの内容はまったく同じであるということで、ECSサービスはコンテナイメージpush後に更新していませんでした。

すなわち、ECSタスク定義で参照しているECRコンテナイメージと、ECR上の最新のコンテナイメージで、実体が違う状態でした。

この状態で、何らかの原因でECSタスクが停止した場合、ECSサービスのDesiredCount:1をおかげでタスクを自動で起動してくれるのですが、以下のエラーが発生してタスクの再起動に延々と失敗していました。

CannotPullContainerError: pull image manifest has been retried 1 time(s): failed to resolve ref xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/aws-test-ecr:001@sha256:yyyyyyyyyyyyyyyy: xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/aws-test-ecr:001@sha256:yyyyyyyyyyyyyyyy: not found

スクリーンショット 2025-04-18 9.54.39

ログの内容を読んでみると、ECSタスク定義にて特定のダイジェストを参照している一方で、そのダイジェストを持つコンテナイメージが存在しない、ということがわかります。ECRに保存するコンテナイメージのタグは一緒(いわゆるlatest運用)なので、「参照しているARNは一緒だが中身が違う」という状態になっています。

こちらの挙動は、次の記事でも詳しく紹介されています。

https://dev.classmethod.jp/articles/amazon-ecs-container-image-scheduling-logic-change/

解決策

ECSサービスを更新すれば、コンテナイメージのダイジェストが最新のECRコンテナイメージのものになるため、ECSタスク自動起動の際にエラーが出なくなるはずです。

そもそもECRのコンテナイメージは、可能であれば、latest運用ではなくコンテナイメージごとにIDなど付ける運用方式が望ましいです。

https://dev.classmethod.jp/articles/ecr-immutable-image-tags/

今回のエラーは、仮にlatest運用している状態であってもECSのサービス更新自動化により防げるかと思いますので、CI/CDでECSサービス時更新の処理追加も現実的な解決策になります。

ただ、CI/CDで毎回ECSサービスを更新していると、ECSへの構成変更が頻繁に発生することになるため、AWS Config(以下、Config)の課金が増加するなどの可能性があります。運用コスト・人的ミス発生時の影響度合いと、Configなどによる料金増加のバランスを考えながら、CI/CDを設定しましょう。

タスク定義の設定でもこの問題は回避できる

今回の前提条件として、「頻繁なタスク定義の更新は抑える」という要件がありましたので、メインの解決策としては扱わなかったのですが、本来であればイメージダイジェスト関係の挙動は、タスク定義のversionConsistencyというパラメータで制御できます。

https://dev.classmethod.jp/articles/amazon-ecs-configure-software-version-consistency/#%25E3%2582%2584%25E3%2581%25A3%25E3%2581%25A6%25E3%2581%25BF%25E3%2581%259F

タスク定義を編集できる状態であれば、"versionConsistency": "disabled"のキーバリューを追加しましょう。この項目を追加していれば、タスク起動時にイメージダイジェストの変換を行わないので、デプロイを実施せずとも大丈夫です。

{
 "family": "nginx-samples",
 "containerDefinitions": [
 	{
+		"versionConsistency": "disabled",
 		"name": "nginx",

latest運用しているECRコンテナイメージを更新したら、要件によってはECRサービスも更新する必要があるかも

タスクのオーケストレーション動作に影響するため、タスク定義をあまり修正できないような要件だと、ECSの再デプロイも選択肢に入ってきます。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.