ECS タスク定義の image の挙動について
Fargate 起動タイプでの Amazon ECS タスク定義パラメータ - Amazon Elastic Container Service
タスク定義のイメージパスでタグまたはダイジェストを指定しない場合、Amazon ECS コンテナエージェントは指定されたイメージの最新バージョンを取り込みます。
上記挙動について調査したところ、以下の挙動でした。
- イメージ更新後に新規タスクを起動した場合、更新前のイメージが使用される
- イメージ更新後に「新しいデプロイの強制」で新規タスクを起動した場合、更新後のイメージが使用される
イメージの作成
まずはコンテナイメージを作成して ECR にプッシュします。
コンテナイメージは以下のブログを参考に作成しました。
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" ]
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 で表示する内容を変更します。
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