今回はAWS ECSサービスに関する記事です。
Azure のコンテナサービス(App Service)をAWSへ移植するために必要な構成を解説していきます。
本記事はシリーズ構成の第二弾として、ECS Fargateの設定準備に向け
コンテナイメージをPushするところまで解説します。
前回記事はこちら⇩

Azure経験者がAWS ECSで同じ構成を作ってみる② ~Image Push~
実装内容
前回記事では、事前準備の部分(1-5) を解説しました。
- Route53
- IAMロール
- DynamoDB
- ECR
- S3
- IAMユーザー
- GitHub
- ECSタスク定義
- ECS Service
- ALB
イメージは以下。
長くなるので記事を分割します。
今回はImage Pushまでの部分(6-7)を設定していきます。
イメージは以下。

構築前の補足説明
AWS ECSのAzureとの違い
App Serviceではアプリが未配置でもサービスだけ先に作成できます。
一方、ECSは「実行するコンテナ」が決まって初めてサービスを作成する設計です。
そのため、ECRへのイメージ登録後にTask DefinitionやServiceを完成させる流れになります。
AWSではリソース全展開だけまず実施する、ということができません。
何かしらのImageを配置しておく必要があり、
段取り的にはAzureより少し面倒です。
各種構築
IAMユーザー
GitHub ActionsからコンテナイメージをAWSへPushできるよう
IAMユーザーを作成していきます。
■GitHub Actions用 IAMユーザー作成
- IAMユーザー名:ecs-github-user
- アクセスキー発行
- 管理ポリシー:
AmazonEC2ContainerRegistryPowerUser
AmazonECS_FullAccess - インラインポリシー:IAM-PassRole-ECS
(1) IAMユーザーの作成

(2) IAMユーザー名を入力
マネコンアクセスのレ点は不要です。

(3) 管理ポリシーを順次アタッチ
以下の管理ポリシーを付与していきます。
- AmazonEC2ContainerRegistryPowerUser
- AmazonECS_FullAccess

(4) インラインポリシーの作成
(3)で設定した管理ポリシーには
iam:PassRole(AWSサービスへIAMロールを引き渡す権限)
が含まれていないため、個別作成します。
※管理ポリシーにはユーザーが定義したIAMロールを、ピンポイント指定するPass定義は存在しません

ポリシーエディタへ以下を記入します。
※AWSアカウントIDはご自身の環境に合わせてください。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": [
"arn:aws:iam::[AWSアカウントID]:role/ecs-task-role",
"arn:aws:iam::[AWSアカウントID]:role/ecs-task-execution-role"
]
}
]
}
ポリシーを作成します。
- IAM-PassRole-ECS

(5) インラインポリシーのアタッチ
作成したインラインポリシーをアタッチします。
※「更新」を押すと一覧で検索できるようになります

(6) 確認して作成
ココまで順調なら、以下のように表示されているはずです。
問題なければ作成します。
※IAMユーザー名以外は後で修正可能

■アクセスキーを発行
作成したIAMユーザーを開き、「セキュリティ認証情報」のタブを開きます。
上部の「アクセスキーを作成」を押下すると、アクセスキー発行の手続きへ進みます。
※下部を押下しても良い

以下のように選択して次へ進みます。

こちらはユースケースに対してAWSが適切な案内をするために設けられているものです。
なので、実際どれを選んでも問題ない です。
現在はGitHub ActionsとAWSをOIDCで連携し、
一時認証情報を利用する構成が推奨されています。
本記事ではAzure App Serviceの構成との比較を分かりやすくするため、
IAMユーザー+アクセスキーを使用しています。
タグは必要ありません。

アクセスキー/シークレットキーはCSVダウンロードするなりして控えておきます。
※このあとGitHubのsecretsへ設定します

GitHub設定
GitHubは空のリポジトリが準備されている前提とします。
筆者は「sandbox」という名前で作成していますが、リポジトリ名はなんでも構いません。
※プライベートリポジトリとして生成することを忘れないでください。
空のリポジトリに対して、まずは以下Keyのsecretsを設定します。
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
■secrets設定
[Settings]-[Secrets and variables]-[Actions]の順に遷移し、[New repository secret]
をクリックします。

2項目設定を行います。
※初回のNew secretは正確にコピペで登録しても、何故か読込できないことがありますので、
不安な方は登録したsecretsをパラメータ更新して同じ値を再度貼り付けてみてください
筆者の体験では2個目以降は発生しないです

以下、本記事のsecrets登録最終形です。

■資源を個別作成
以下の資源を個別作成していきます。(4ファイル分)
[リポジトリ名]/
├── .github/
│ └── workflows/
│ └── deploy.yml
├── Dockerfile
├── app.py
└── requirements.txt
[.github/workflows/deploy.yml]
以下のコードを貼り付けします。
ファイル名に小タイトルのフルパスを入力すれば、意図したフォルダ構成で自動生成されます。
※あらかじめフォルダを切る必要はありません
name: Build and Push Docker Image
on:
push:
tags:
- "v*"
workflow_dispatch:
env:
AWS_REGION: ap-northeast-1
ECR_REPOSITORY: ecs-sample-api
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v5
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Set image tag
id: image-tag
shell: bash
run: |
if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
echo "value=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"
else
echo "value=manual-${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
fi
- name: Build and push Docker image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ steps.image-tag.outputs.value }}
run: |
IMAGE_URI="$ECR_REGISTRY/$ECR_REPOSITORY"
docker build \
-t "$IMAGE_URI:$IMAGE_TAG" \
-t "$IMAGE_URI:latest" \
.
docker push "$IMAGE_URI:$IMAGE_TAG"
docker push "$IMAGE_URI:latest"
[Code]タブの[+]を押下すると[Create new file] が表示されるのでココから作成します。

ファイル名は左上あたりへフルパスを入力すると自動的に以下の表示になります。
コード部へ上記Yamlを貼付します。
最後に右上の[Commit change]を押下します。

ポップアップが上がってきますが、そのまま[Commit changes]を押下して問題ないです。
※開発者が「このバージョンは何を変えた」など履歴を記載できる機能です
検証で利用する分には適当に扱って問題ありません

[app.py]
同じ要領でどんどん作成します。
from flask import Flask, jsonify
from flask_cors import CORS
app = Flask(__name__)
# S3静的WebサイトからAPIを呼び出せるようにする
CORS(app)
@app.get("/")
def root():
return jsonify({
"message": "Hello from AWS ECS!"
})
@app.get("/api")
def api():
return jsonify({
"message": "Hello from AWS ECS!"
})
@app.get("/health")
def health():
return jsonify({
"status": "ok"
})
if __name__ == "__main__":
app.run(
host="0.0.0.0",
port=8080
)
[requirements.txt]
Flask==3.1.2
flask-cors==6.0.1
gunicorn==23.0.0
[Dockerfile]
FROM python:3.13-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install \
--no-cache-dir \
-r requirements.txt
COPY app.py .
EXPOSE 8080
CMD ["gunicorn", "--bind", "0.0.0.0:8080", "app:app"]
■GitHub Release 実行(コンテナイメージのPush)
ココまで進めたら、GitHubからAWSに対して、ImageをPush出来る準備が整っています。
Code直下が以下のような構成になっていることを確認します。
※ReadMeは、なくても動きます。ちゃんと開発する段階になったら清書すべきものです
(1) GitHub Release実行
Release をクリックします。
初回等で押下できない場合は、すぐ下にある[Create a new release]を代わりに押下します。

[Tag: Select tag]を押下すると、[Create new tag]が表示されるので、押下します。
画面中央に以下のようにポップアップが表示されるので、[v1.0.0]と入力します。
※再実行する場合はv1.0.1 のように、すでにあるTagと被らないように作成します。
なお、本記事で解説しているReleaseの利用方法は「タグフック型」となります。

タグ設定後は、[Release title]へ生成したタグ名を記入します。
さらに[Generate release notes]を押下すると、notes へ自動的に記入されます。

下へスクロールして、[Publish release]を実行します。

[Actions]タブをクリックすると、先程リリースしたWorkFlowが実行中のはずです。
押下して進捗をチェックします。

以下のように正常終了したことを確認します。
※Re-runも可能ですが、本記事程度の使い方で失敗することはほぼなく、実行時間も1-2分程度です

AWSのECRもチェックします。以下のようにImage Pushされたことが確認できればOKです。

ECS起動編へ続く
このあとの手順は次の記事にて解説していきます。
※鋭意作成中
またECSの設定とあわせて、本記事では以下の設定について解説いたしました。
- コンテナイメージ生成用の資源作成
- GitHub Release (タグフック型) の実行方法
関連記事のご紹介
シリーズ初回記事



コメント