📝

ECS タスク定義の image の挙動について

に公開

Fargate 起動タイプでの Amazon ECS タスク定義パラメータ - Amazon Elastic Container Service

タスク定義のイメージパスでタグまたはダイジェストを指定しない場合、Amazon ECS コンテナエージェントは指定されたイメージの最新バージョンを取り込みます。

上記挙動について調査したところ、以下の挙動でした。

  • イメージ更新後に新規タスクを起動した場合、更新前のイメージが使用される
  • イメージ更新後に「新しいデプロイの強制」で新規タスクを起動した場合、更新後のイメージが使用される

イメージの作成

まずはコンテナイメージを作成して ECR にプッシュします。
コンテナイメージは以下のブログを参考に作成しました。

Dockerfile
FROM node:22-alpine
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY . .
RUN npm init -y
RUN npm install express
EXPOSE 80
CMD [ "node", "index.js" ]
index.js
const express = require("express");
const app = express();

app.get("/", (req, res) => {
  res.send("Welcome from a Node.js app!");
});

app.listen(80, () => {
  console.log("Server is up on 80");
});

ECR へのプッシュはコンソールで表示されるプッシュコマンド通りに実行します。

$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 012345678901.dkr.ecr.ap-northeast-1.amazonaws.com

$ docker build -t test .

$ docker tag test:latest 012345678901.dkr.ecr.ap-northeast-1.amazonaws.com/test:latest

$ docker push 012345678901.dkr.ecr.ap-northeast-1.amazonaws.com/test:latest

プッシュしたイメージをビルドしてアクセスすると以下のような画面が表示されます。

この時点では ECR には latest タグのイメージが 1 つだけプッシュされています。

ECS サービスの作成

タスク定義のコンテナ定義のイメージ URI に上記イメージを指定します。
イメージの指定方法は latest タグを参照する方法です。

作成したタスク定義を使用して ECS サービスを作成します。
起動したタスクのイメージダイジェストは以下の通りです。

  • sha256:0027a33333d5aefb9f81248cbf435035f12468d75bf9b98fdd854cd84ce35497

タスクのパブリック IP にアクセスし、アプリケーションが表示されることを確認します。

イメージの更新

上記のイメージを更新して再度 ECR にプッシュします。
index.js で表示する内容を変更します。

index.js
const express = require("express");
const app = express();

app.get("/", (req, res) => {
  res.send("This image was updated");
});

app.listen(80, () => {
  console.log("Server is up on 80");
});

ECR には最新の latest タグのイメージと最初にプッシュしたイメージが存在する状況になりました。

この状態で既存のタスクを停止し、Auto Scaling によって新規タスクを起動してみます。

新しく起動したタスクのイメージダイジェストは以下の通り、停止したタスクのイメージダイジェストと同じでした。

  • sha256:0027a33333d5aefb9f81248cbf435035f12468d75bf9b98fdd854cd84ce35497

タスクのパブリック IP にアクセスしても更新前のアプリケーションが表示されます。

同じタグでイメージを更新した場合の挙動について

UpdateService - Amazon Elastic Container Service

If your updated Docker image uses the same tag as what is in the existing task definition for your service (for example, my_image:latest), you don't need to create a new revision of your task definition. You can update the service using the forceNewDeployment option. The new tasks launched by the deployment pull the current image/tag combination from your repository when they start.

上記の通り、同じタグでイメージを更新した場合、最新のイメージを使用するためには forceNewDeployment オプション、つまり「新しいデプロイの強制」でタスクを起動する必要があります。

実際に「新しいデプロイの強制」でタスクを起動してみます。

新しく起動したタスクのイメージダイジェストは以下の通り、停止したタスクのイメージダイジェストと異なっていました。

  • sha256:78abd6bebcddbb11d847a3edb4e5df03f4066a71487ed7a20e4b1e3e3a80c1b8

上記最新のイメージダイジェストは ECR の最新のイメージダイジェストと同じであることも確認できました。

タスクのパブリック IP にアクセスし、更新後のアプリケーションが表示されることも確認できました。

以上の結果より、以下の挙動を確認できました。

  • イメージ更新後に新規タスクを起動した場合、更新前のイメージが使用される
  • イメージ更新後に「新しいデプロイの強制」で新規タスクを起動した場合、更新後のイメージが使用される

まとめ

今回は ECS タスク定義の image の挙動について紹介しました。
どなたかの参考になれば幸いです。

参考資料

Discussion