Github ActionsでECS on EC2へデプロイするハンズオン
こんにちは!バックエンドエンジニアのshunです。
突然ですが皆さんはECS上でコンテナを実行するインフラストラクチャはFargateを選択していますか?それともEC2を選択していますか?
最近はFargateのアップデートも進み、より便利にサーバレスで利用できるFargateが選ばれるケースも多いかと思いますが、プロジェクトの要件によってはEC2が選択されるプロジェクトももちろん多くあるかと思います!
ちなみにFargateはサーバレスで便利な反面、数年前まではセキュリティの観点からコンテナへログインがでない仕様だったため緊急時のトラブルシューティングが難しいという観点もあり、弊社でもEC2を選択しているプロジェクトがあります。そのため、今回は業務でも触る機会のあるECS on EC2を改めて自分で構築して理解を定着させたいと思います👍
※現在ではFargateのコンテナにもログインできるような仕様になっているため[1]、弊社でもECS上のコンテナ実行環境のファーストチョイスはFargateになりました。
前置き
このセクションではハンズオンを読み進めていただく上での前提条件や、完成したworkflowファイルを先に掲載していますので、ハンズオンを読み進めていただく前に是非ご確認ください。
ハンズオンの構成図
構成は以下です。大きな工程としてはmainブランチへマージ(もしくはプッシュ)すると、最新のGitHubのリモートリポジトリのイメージがビルドされECRにプッシュされます。その後、更新されたタスク定義が実行され、ECS内でコンテナがデプロイされる仕組みを構築していきます。

GitHub Actionsのworkflowテンプレートをベースにします
GitHub ActionsでECSへデプロイするworkflowファイルはGitHubページからテンプレートを取得できます。今回のハンズオンも公式のテンプレートをベースにしていますが、この記事では順を追って作成するので先にテンプレートをリポジトリに作成しておかなくてもOKです。テンプレートをベースに編集を加えていく場合は以下を参考にGitHubページからテンプレートを取得できますので良ければご参照ください。
ECS on EC2へデプロイするGitHub Actionsのworkflowテンプレート
Actions > New workflowボタン

ECS検索しConfigureボタン

Commit changes...ボタン

先にハンズオンの完成版のworkflowを見たい方へ
今回の完成版のworkflowを先に確認したい方はこちらでご確認いただけます。今回のハンズオンでは、AWSへの認証、環境変数やタスク定義の取り扱いはGitHub Actionsのworkflowのテンプレートに準じていますので、もしご活用される際は適宜ご自身のプロジェクトに置き換えてください😌
完成版のGitHub Actionsのworkflow
name: Deploy to AWS
# トリガー条件
# このワークフローは、mainブランチにマージ(変更がプッシュ)されたときに実行されます。
on:
push:
branches: ["main"]
# 環境変数の設定
# 必要な情報を環境変数として指定。
# (ハンズオンでは、AWSリージョン、リポジトリ名、クラスター、サービス名、タスク定義ファイル名などの順次追加していきます)
env:
AWS_REGION: ap-northeast-1
ECR_REPOSITORY: testrepo
ECS_CLUSTER: test-cluster
ECS_SERVICE: test-service
CONTAINER_NAME: testrepo
ECS_TASK_DEFINITION: testrepo-task-revision1.json
# ジョブの構成
# deployという名前のジョブを設定し、Ubuntu環境でGitHub Actionsを実行します。
jobs:
deploy:
name: deploy
runs-on: ubuntu-latest
steps:
# リポジトリのチェックアウト
# actions/checkoutを使用して、GitHubリポジトリの内容をクローン。
- name: Checkout
uses: actions/checkout@v4
# AWS認証情報の設定
# aws-actions/configure-aws-credentialsを使用して、GitHubのシークレットに保存したAWSアクセスキーとシークレットキーを用いて認証。
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
# ECRへのログイン
# aws-actions/amazon-ecr-loginを使用して、Amazon ECRにログイン。
# (このステップで取得したレジストリ情報は後続のステップで使用されます)
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
# Dockerイメージのビルドとプッシュ
# docker buildコマンドでDockerイメージをビルドし、ECRリポジトリにプッシュ。
# 成功後、ビルドしたイメージのタグを出力として保存します。
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
run: |
docker build --no-cache -t $ECR_REGISTRY/$ECR_REPOSITORY:latest .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:latest" >> $GITHUB_OUTPUT
# タスク定義の更新
# aws-actions/amazon-ecs-render-task-definitionを使用して、新しいDockerイメージを指定したタスク定義ファイルを更新。
# これにより、ECSサービスにデプロイされるコンテナが最新のイメージを使用するようになります。
- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: ${{ env.ECS_TASK_DEFINITION }}
container-name: ${{ env.CONTAINER_NAME }}
image: ${{ steps.build-image.outputs.image }}
# デプロイの実行
# aws-actions/amazon-ecs-deploy-task-definitionを使用して、更新されたタスク定義を実行しECSにデプロイ。
# この際、強制的に新しいデプロイを開始する設定を有効にしています。
- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: ${{ env.ECS_SERVICE }}
cluster: ${{ env.ECS_CLUSTER }}
wait-for-service-stability: false
force-new-deployment: true
AWSの認証に関する補足
セクションの冒頭で記載しましたが今回はGitHub Actionsのworkflowのテンプレートをベースにしているため、AWSのアクセスキーとシークレットアクセスキーを活用する方式を採っています。
OpenID Connect (OIDC)方式で認証を行いたい方はこちらの記事でもわかりやすく紹介されているので是非ご参照ください。
※弊社でもセキュリティ強化の観点から順次OpenID Connect (OIDC)方式へ切り替えているため、このハンズオンも別の機会にブラシュアップしたいと思います!
どの端末、サービス上で操作するかの目印
セクションの冒頭でどの環境で操作するかを明記します。ハンズオンの際は参考にしてください。
例: AWSマネジメントコンソール上で操作の場合 ↓
【1】GitHub ActionsでAWSにログインしよう
では早速ハンズオンを開始します!
【1-*】では、まずはGitHub ActionsでAWSにログインするところまで進めます。
【1-1】AWSのアクセスキーとシークレットアクセスキーを作成
今回はGitHub ActionsからAWSへの認証にはAWSのアクセスキーとシークレットアクセスキーを活用する方式を採用するため、AWSマネジメントコンソールで以下手順で作成していきます。
IAM > ユーザー画面で対象のユーザーを選択してください。

セキュリティ認証情報タブを選択し、アクセスキーを作成ボタンを押します。

画面を進めると、アクセスキーとシークレットアクセスキーを作成できます。画面にも表示されますが、あとでわからなくなると困るのでcsvでダウンロードしておくと良いでしょう。(この情報はセキュアなため外部に漏れないようにしてください)

【1-2】GitHubにアクセスキーとシークレットアクセスキーを保存
前の章でAWSの認証に必要な情報は作成できたので、GitHub ActionsでAWSに接続できるか確認してみましょう。
先程AWSマネジメントコンソールで作成したアクセスキーとシークレットアクセスキーをGitHub側で管理(保存)します。
GitHub Actionsを実行するリポジトリのSettings > Secrets and variables > Actioins を選択後、New repository secretボタンを押してシークレットを登録できる画面に進んでください。


NameとSecretを入力できる画面に遷移するので、以下の表を参考に入力し保存してください。2つの情報を保存するため保存作業は2回行います。
| Name | Secret |
|---|---|
| AWS_ACCESS_KEY_ID | 先程作成したアクセスキーをペースト |
| AWS_SECRET_ACCESS_KEY | 先程作成したシークレットアクセスキーをペースト |
保存作業が完了し以下のような画面になればOKです!

【1-3】AWSへの認証をテスト
workflowファイルを作成
GitHub Actionsのworkflowsを実行するには、決められたディレクトリ構成でYAMLファイルを格納する必要があるので、まずは.github/workflows/ディレクトリを作成し任意のファイル名のYAMLファイルを作成します。今回はdeploy-aws.ymlというワークフロー用のファイルを作成しました。
+ ├── .github
+ └── workflows
+ └── deploy-aws.yml
セクションの冒頭に説明したように、このセクションではAWSにログインできるところまでのワークフローを作成します。(ECRへのイメージのプッシュや、ECSへのデプロイは【2】【3】セクションで行います)
+ name: Deploy to AWS
+
+ # トリガー条件
+ # このワークフローは、mainブランチにマージ(変更がプッシュ)されたときに実行されます。
+ on:
+ push:
+ branches: ["main"]
+
+ # 環境変数の設定
+ # 必要な情報を環境変数として指定。
+ # (ハンズオンでは、AWSリージョン、リポジトリ名、クラスター、サービス名、タスク定義ファイル名などの順次追加していきます)
+ env:
+ AWS_REGION: ap-northeast-1
+
+ # ジョブの構成
+ # deployという名前のジョブを設定し、Ubuntu環境でGitHub Actionsを実行します。
+ jobs:
+ deploy:
+ name: deploy
+ runs-on: ubuntu-latest
+
+ steps:
+ # AWS認証情報の設定
+ # aws-actions/configure-aws-credentialsを使用して、Githubのシークレットに保存したAWSアクセスキーとシークレットキーを用いて認証。
+ - name: Configure AWS credentials
+ uses: aws-actions/configure-aws-credentials@v1
+ with:
+ aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ aws-region: ${{ env.AWS_REGION }}
+
+ # IAMユーザー情報の取得
+ # aws iam get-userコマンドを使用して、現在使用しているAWS認証情報に紐付けられたIAMユーザーの詳細を取得します。
+ - name: execute AWS CLI
+ run: aws iam get-user
次の章に進む前に、上記のYAMLファイルを作成したらリモートリポジトリへプッシュしておきましょう。
workflowの動作確認
今回のworkflowはmainブランチにマージすることで実行されます。前回の章でローカルリポジトリで作成したworkflowファイルをプッシュしたと思うので、GitHub上でmainブランチへ向けたプルリクエストを作成しマージしてください。
mainブランチへマージしたらGitHub上のActionsタブを選択し、サイドメニューの実行したワークフローを選択しましょう。

ログを確認しworkflowファイルの最後に実行したaws iam get-userコマンドの出力結果が表示されていれば、無事GitHub ActioinsでAWSと認証できているのでOKです!

【2】ECRにイメージをプッシュしよう
AWS Elastic Container Registry (ECR) は、Dockerコンテナイメージを保存・管理するためのフルマネージドなサービスです。Docker HubのAWS版というイメージです。
【2-1】 ECRのリポジトリを作成
ECR > Repositoriesメニューを選択し、リポジトリを作成ボタンからプライベートリポジトリを作成します。今回はtestrepoというリポジトリを作成しました。

まだイメージのプッシュ前なので、testrepoの中身は空っぽでOKです。

【2-2】 ECRのリポジトリにイメージをプッシュ
Dockerfileを作成
ECRにはDockerイメージをプッシュするため、Dockerfileを追加します。
FROM httpd:2.4
COPY test.txt /usr/local/apache2/htdocs/test.txt
また、このタイミングで最終的にECSへデプロイするtest.txtも一緒に作っておきましょう。
Hello World!!
├── .github
│ └── workflows
│ └── deploy-aws.yml
+ ├── Dockerfile
+ └── test.txt
workflowファイルを修正
イメージをビルドし、ECRへプッシュする処理を追加します。また、【1-3】で記述したAWSとの認証ができているかテストするためのIAMユーザー情報を取得する処理は不要なので削除しておきます。
name: Deploy to AWS
# トリガー条件
# このワークフローは、mainブランチにマージ(変更がプッシュ)されたときに実行されます。
on:
push:
branches: ["main"]
# 環境変数の設定
# 必要な情報を環境変数として指定。
# (ハンズオンでは、AWSリージョン、リポジトリ名、クラスター、サービス名、タスク定義ファイル名などの順次追加していきます)
env:
AWS_REGION: ap-northeast-1
+ ECR_REPOSITORY: testrepo
# ジョブの構成
# deployという名前のジョブを設定し、Ubuntu環境でGitHub Actionsを実行します。
jobs:
deploy:
name: deploy
runs-on: ubuntu-latest
steps:
+ # リポジトリのチェックアウト
+ # actions/checkoutを使用して、GitHubリポジトリの内容をクローン。
+ - name: Checkout
+ uses: actions/checkout@v4
# AWS認証情報の設定
# aws-actions/configure-aws-credentialsを使用して、Githubのシークレットに保存したAWSアクセスキーとシークレットキーを用いて認証。
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- # IAMユーザー情報の取得
- # aws iam get-userコマンドを使用して、現在使用しているAWS認証情報に紐付けられたIAMユーザーの詳細を取得します。
- - name: execute AWS CLI
- run: aws iam get-user
+ # ECRへのログイン
+ # aws-actions/amazon-ecr-loginを使用して、Amazon ECRにログイン。
+ # (このステップで取得したレジストリ情報は後続のステップで使用されます)
+ - name: Login to Amazon ECR
+ id: login-ecr
+ uses: aws-actions/amazon-ecr-login@v1
+
+ # Dockerイメージのビルドとプッシュ
+ # docker buildコマンドでDockerイメージをビルドし、ECRリポジトリにプッシュ。
+ - name: Build, tag, and push image to Amazon ECR
+ id: build-image
+ env:
+ ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
+ run: |
+ docker build --no-cache -t $ECR_REGISTRY/$ECR_REPOSITORY:latest .
+ docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
上記のファイルを作成したらリモートリポジトリへプッシュしておきましょう。
GitHub ActionsでECRにプッシュできるか確認
GitHub上でmainブランチへ向けたプルリクエストを作成し、マージしてください。
先ほど空っぽだったECRのリポジトリにイメージがプッシュされていればOKです!

【3】ECS on EC2へデプロイしよう
ECSは、Amazon Elastic Container Service(Amazon ECS)の略で、AWS上でDockerコンテナのデプロイや運用管理を効率化するためのフルマネージドなコンテナオーケストレーションサービスです。
前のセクションでmainブランチへのマージをトリガーに、GitHub ActionsでECRにイメージをプッシュできました。このセクションではそのDockerイメージのコンテナの実行環境を作成していきます。
AWSマネジメントコンソール上でクラスター、タスク定義、サービスの順に作成し、その後、GitHub Actionsのworkflowファイルを修正する手順で進めます。
※以降のセクションではECS関連のAWSリソースは設定のみ掲載します。 クラスター、タスク定義、サービスに関する詳細は割愛するため事前に詳しく知りたい方は以下がおすすめです。
【3-1】クラスター作成
ECS > クラスターメニューを選択し、クラスターの作成ボタンから作成します。
設定
クラスター設定
| 項目 | 設定 |
|---|---|
| クラスター名 | test-cluster |
インフラストラクチャ
Amazon EC2 インスタンスを選択してください。
| 項目 | 設定 |
|---|---|
| プロビジョニングモデル | オンデマンド |
| EC2 インスタンスタイプ | t2.large (※1) |
| 必要な容量 | 最小1~最大5 (※2) |
| SSHキーペア | 今回は新しく作りました (※3) |
Amazon EC2 インスタンスのネットワーク設定
| 項目 | 設定 |
|---|---|
| パブリック IP の自動割り当て | オンにする |
補足
- (※1)この後、タスク定義でCPU1Gとメモリ3Gのコンテナを起動することを指定します。GitHub Actionsでデプロイする際に一時的に2つのコンテナ(起動中のコンテナとこれから入れ替わるコンテナ)が共存するため、大きめのインスタンスタイプを指定しています。
- (※2)最小1にしておかないとクラスター内のコンテナインスタンスが1つも起動しないので、最小は1にしておいてください。
- (※3)あとでクラスターのコンテナインスタンス(ECS on EC2)にログインして、実行中のコンテナの中身を確認するのでSSH接続できるようにキーペアを指定してください。このハンズオンではキーペアのファイルはローカルの
.ssh/に置いています。

クラスター作成後
【3-2】タスク定義
ECS > タスク定義メニューを選択し、新しいタスク定義の作成ボタンから作成します。
設定
タスク定義の設定
| 項目 | 設定 |
|---|---|
| タスク定義ファミリー | testrepo-task |
インフラストラクチャの要件
| 項目 | 設定 |
|---|---|
| 起動タイプ | Amazon EC2 インスタンス |
| ネットワークモード | bridge |
| タスクロール | ecsTaskExecutionRole |
コンテナ
| 項目 | 設定 |
|---|---|
| 名前 | testrepo |
| イメージURL | {ご自身のアカウントID}.dkr.ecr.ap-northeast-1.amazonaws.com/testrepo:latest |

タスク定義後
タスク定義のjsonファイルをダウンロード
後の工程で必要になるため、作成したタスク定義のjsonファイルをダウンロードしておいてください。

【3-3】サービス作成
ECS > クラスターメニューを選択し、【3-1】で作成したtest-clusterを選択した画面からサービスを作成します。

設定
環境
| 項目 | 設定 |
|---|---|
| 起動タイプ | EC2 |
デプロイ設定
| 項目 | 設定 |
|---|---|
| ファミリー | testrepo-task |
| サービス名 | test-service |

サービス作成後
ECRのイメージがコンテナで実行されているか確認
サービスを作成して数分待つとタスクが実行されタスク定義で指定したECRのtestrepoリポジトリのイメージが、コンテナインスタンス(ECS on EC2)の中でコンテナ実行されているため、実際にコンテナインスタンス(ECS on EC2)へログインしてコンテナの中身を確認します。
それでは、まずはtest-clusterページのインフラストラクチャタブのコンテナインスタンスセクションから起動中のEC2を選択します。

コンテナインスタンス(ECS on EC2)の画面からパブリックIPをコピーします。今回は3.112.213.79でした。

ターミナルを開いたら【3-1】で指定したSSHキーがあるディレクトリへ移動し、コンテナインスタンス(ECS on EC2)へログインします。
# SSHキーがあるディレクトリへ移動
cd ~./ssh
# コンテナインスタンス(ECS on EC2)へ接続
ssh -i {SSHキーのファイル名}.pem ec2-user@3.112.213.79
コンテナインスタンス(ECS on EC2)へログインできたら、起動中のコンテナを確認します。実行のコンテナIDは4d72db491210でした。
[ec2-user@ip-10-0-0-58 ~]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4d72db491210 640168413381.dkr.ecr.ap-northeast-1.amazonaws.com/testrepo:latest "httpd-foreground" 41 minutes ago Up 41 minutes 0.0.0.0:32780->80/tcp, :::32780->80/tcp ecs-testrepo-task-7-testrepo-dea9b984a7cca8d37d00
c5af6e906148 amazon/amazon-ecs-agent:latest "/agent" 4 hours ago Up 4 hours (healthy) ecs-agent
c5af6e906148のECSコンテナエージェントについて
ECSコンテナエージェント
一番下に表示されているc5af6e906148 amazon/amazon-ecs-agent:latestコンテナプロセスは、コンテナインスタンス(ECS on EC2)内でコンテナオーケストレーションを実現させるためのタスク管理などを行うシステムです。
そのため、タスク定義で起動するアプリケーションコンテナプロセス(今回は4d72db491210)とは別のシステムコンポーネントです。
【2-2】でECRにプッシュされたtestrepoリポジトリのイメージがコンテナ実行されているか確認するため、さらにコンテナに入り【2-2】のDockerFileで指定した位置のtest.txtの中身を確認してみます。
# コンテナに入りbashを起動
[ec2-user@ip-10-0-0-58 ~]$ docker exec -i -t 4d72db491210 bash
# コンテナ内でtest.txtの中身を表示
root@4d72db491210:/usr/local/apache2# cat /usr/local/apache2/htdocs/test.txt
Hello World!!
Hello World!!を確認できればOKです!
補足
※次の工程でもコンテナインスタンス(ECS on EC2)内でコンテナの状況を確認するため、一旦コンテナから出てコンテナインスタンス(ECS on EC2)に接続した状態にしておいてください。
root@4d72db491210:/usr/local/apache2# exit
exit
[ec2-user@ip-10-0-0-58 ~]$
【3-4】デプロイ
workflowファイルを修正
【3-2】でダウンロードしたタスク定義のjsonファイルをアップロードしてください。
├── .github
│ └── workflows
│ └── deploy-aws.yml
├── Dockerfile
├── test.txt
+ └── testrepo-task-revision1.json
workflowファイルにECSのクラスター、タスク定義、サービスの情報とECSクラスター内のコンテナインスタンス(ECS on EC2)にデプロイする処理を追加します。
name: Deploy to AWS
# トリガー条件
# このワークフローは、mainブランチにマージ(変更がプッシュ)されたときに実行されます。
on:
push:
branches: ["main"]
# 環境変数の設定
# 必要な情報を環境変数として指定。
# (ハンズオンでは、AWSリージョン、リポジトリ名、クラスター、サービス名、タスク定義ファイル名などの順次追加していきます)
env:
AWS_REGION: ap-northeast-1
ECR_REPOSITORY: testrepo
+ ECS_CLUSTER: test-cluster
+ ECS_SERVICE: test-service
+ CONTAINER_NAME: testrepo
+ ECS_TASK_DEFINITION: testrepo-task-revision1.json
# ジョブの構成
# deployという名前のジョブを設定し、Ubuntu環境でGitHub Actionsを実行します。
jobs:
deploy:
name: deploy
runs-on: ubuntu-latest
steps:
# リポジトリのチェックアウト
# actions/checkoutを使用して、GitHubリポジトリの内容をクローン。
- name: Checkout
uses: actions/checkout@v4
# AWS認証情報の設定
# aws-actions/configure-aws-credentialsを使用して、Githubのシークレットに保存したAWSアクセスキーとシークレットキーを用いて認証。
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
# ECRへのログイン
# aws-actions/amazon-ecr-loginを使用して、Amazon ECRにログイン。
# (このステップで取得したレジストリ情報は後続のステップで使用されます)
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
# Dockerイメージのビルドとプッシュ
# docker buildコマンドでDockerイメージをビルドし、ECRリポジトリにプッシュ。
+ # 成功後、ビルドしたイメージのタグを出力として保存します。
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
run: |
docker build --no-cache -t $ECR_REGISTRY/$ECR_REPOSITORY:latest .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
+ echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:latest" >> $GITHUB_OUTPUT
+ # タスク定義の更新
+ # aws-actions/amazon-ecs-render-task-definitionを使用して、新しいDockerイメージを指定したタスク定義ファイルを更新。
+ # これにより、ECSサービスにデプロイされるコンテナが最新のイメージを使用するようになります。
+ - name: Fill in the new image ID in the Amazon ECS task definition
+ id: task-def
+ uses: aws-actions/amazon-ecs-render-task-definition@v1
+ with:
+ task-definition: ${{ env.ECS_TASK_DEFINITION }}
+ container-name: ${{ env.CONTAINER_NAME }}
+ image: ${{ steps.build-image.outputs.image }}
+
+ # デプロイの実行
+ # aws-actions/amazon-ecs-deploy-task-definitionを使用して、更新されたタスク定義を実行しECSにデプロイ。
+ # この際、強制的に新しいデプロイを開始する設定を有効にしています。
+ - name: Deploy Amazon ECS task definition
+ uses: aws-actions/amazon-ecs-deploy-task-definition@v1
+ with:
+ task-definition: ${{ steps.task-def.outputs.task-definition }}
+ service: ${{ env.ECS_SERVICE }}
+ cluster: ${{ env.ECS_CLUSTER }}
+ wait-for-service-stability: false
+ force-new-deployment: true
最後にtest.txtの中身を変更しておきます。
- Hello World!!
+ Hello ECS!!
上記の対応が済んだらリモートリポジトリへプッシュしてください。
GitHub Actionsを実行
mainブランチへマージし、GitHub Actionsが実行します。(成功すると黄色からグリーンに変わります)

ECRに新しいイメージが追加されているか確認
ECRに新しいイメージがプッシュされていることを確認します。

コンテナインスタンス(ECS on EC2)内の実行中のコンテナが切り替わるか確認
先程コンテナインスタンス(ECS on EC2)へ接続したターミナルに戻り、コンテナの実行状況を確認します。【3-3】のサービス定義後に作成された4d72db491210コンテナに加え、新たにもう一つb6a9e293ee7dコンテナが起動しています。
[ec2-user@ip-10-0-0-58 ~]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b6a9e293ee7d 640168413381.dkr.ecr.ap-northeast-1.amazonaws.com/testrepo:latest "httpd-foreground" 38 seconds ago Up 38 seconds 0.0.0.0:32781->80/tcp, :::32781->80/tcp ecs-testrepo-task-8-testrepo-eaefba87c5f39dae5300
4d72db491210 4aa03472352c "httpd-foreground" About an hour ago Up About an hour 0.0.0.0:32780->80/tcp, :::32780->80/tcp ecs-testrepo-task-7-testrepo-dea9b984a7cca8d37d00
c5af6e906148 amazon/amazon-ecs-agent:latest "/agent" 4 hours ago Up 4 hours (healthy)
しばらくして再度docker psすると起動中のコンテナから4d72db491210が消え、b6a9e293ee7dの1つのコンテナだけ実行していることがわかります。
[ec2-user@ip-10-0-0-58 ~]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b6a9e293ee7d 640168413381.dkr.ecr.ap-northeast-1.amazonaws.com/testrepo:latest "httpd-foreground" 58 seconds ago Up 57 seconds 0.0.0.0:32781->80/tcp, :::32781->80/tcp ecs-testrepo-task-8-testrepo-eaefba87c5f39dae5300
c5af6e906148 amazon/amazon-ecs-agent:latest "/agent" 4 hours ago Up 4 hours (healthy)
それでは、b6a9e293ee7dへ入りtest.txtの中身を確認してみましょう。
# コンテナへ入りBashを起動
[ec2-user@ip-10-0-0-58 ~]$ docker exec -i -t b6a9e293ee7d bash
#test.txtの中身を確認
root@b6a9e293ee7d:/usr/local/apache2# cat /usr/local/apache2/htdocs/test.txt
Hello ECS!!
test.txtの中身がHello World!!からHello ECS!!になり、無事GitHub Actionsを使って指定のECRのリポジトリの最新のイメージをデプロイできました!
動作確認後の後片付け
AWSリソース
無料利用枠はありますが以下は課金が発生するサービスのため適宜削除してください。
- ECSのクラスター
- ECRのリポジトリ
- ユーザー (ハンズオン用に作成していた場合)
GitHub
【1-2】でGitHubに保存したアクセスキーとシークレットアクセスキーは不要であれば削除してくおくと安心です。
まとめ
今回はGitHub ActionsのworkflowでECSへECRのリポジトリの最新のイメージをデプロイしました!GitHub Actionsは公式のテンプレートや連携するサービスのためのactionもある程度用意されているため使いやすい印象です。また、アプリケーションコードとデプロイ周りの処理を同じリポジトリで管理できるのは、管理コスト面でもアドバンテージがあると感じました。
今回はAWSマネジメントコンソールベースでリソースを作りましたが、今後はこの辺りをCDKで置き換えたり、簡単なGoのAPIを作りGitHub ActionsのworkflowにCIを追加したり、ELB立てて動的ポートマッピングに対して外部からの通信を受けれる構成にしたり、より実務に近い構成に育てていきたいと思っています!👍
Discussion