- はじめに
- キーワード解説
- cdk-asg-webapp との比較
- ファイル構成と役割
- 使用するAWSサービス
- 前提条件
- 作業順序
- ① プロジェクトのセットアップ
- ② GitHub との接続を設定する(CodeConnections)
- ③ cdk.json の設定
- ④ コードを GitHub にプッシュする(重要!)
- ⑤ パイプラインスタックのデプロイ(初回のみ)
- ⑥ パイプラインの実行状況を確認する
- ⑦ インフラを確認する
- ⑧ GitHub Actions を設定する(OIDC + IAM ロール)
- ⑨ アプリを初回デプロイする(GitHub Actions)
- ⑩ ECS Exec でコンテナに接続する
- ⑪ タスク数スケーリングを体験する
- ⑫ リソースを削除する
- EC2 → コンテナへの移行ポイント
- トラブルシューティング
- まとめ
はじめに
「EC2 の OS パッチや Tomcat のインストール設定が面倒」「スケールアウト時のインスタンス管理が複雑」——これを解決するのが ECS Fargate(サーバーレスコンテナ) です。
この記事では、ASG ハンズオン(cdk-asg-webapp)で構築した EC2 + Auto Scaling Group 構成を、ECS Fargate + Docker コンテナにアップグレードします。EC2 の代わりに Docker コンテナで Spring Boot アプリを動かし、GitHub Actions がコンテナイメージをビルドして ECS へ自動デプロイする仕組みを体験します。
【インフラ担当】CDK Pipelines
GitHub リポジトリ
↓ push(常に起動)
CodePipeline (my-cdk6-pipeline)
├── Source: GitHub (CodeConnections 経由)
├── Build(Synth): CodeBuild — cdk synth
├── Mutate: パイプライン自己更新(セルフミューテーション)
└── InfraDeploy: CloudFormation — VPC / ECR / ECS / RDS / ALB
【アプリ担当】GitHub Actions(app/ または Dockerfile 変更時のみ起動)
1. Docker ビルド(Maven → WAR → Tomcat コンテナ)
2. ECR にイメージをプッシュ
3. タスク定義を新リビジョンに更新(プレースホルダー → 実イメージ)
4. ECS サービスをローリングデプロイ(〜2〜3分)
↓
[ALB: my-cdk6-alb]
↓
ECS Fargate Service (my-cdk6-service)
・コンテナ: Tomcat 10.1 + Spring Boot WAR
・CPU: 256 units / Memory: 512 MiB
↓
[RDS: my-cdk6-rds-mysql] ← MySQL 8.0このハンズオンで体験できること:
- Docker のマルチステージビルド(Maven → WAR → Tomcat コンテナ)
- ECR へのイメージプッシュと ECS Fargate でのコンテナ実行
- GitHub Actions(OIDC 認証)による Docker ビルド → ECR プッシュ → ECS ローリングデプロイ
- インフラ(CDK Pipelines)とアプリ(GitHub Actions)のデプロイを分離した実務パターン
- ECS Exec でコンテナ内のシェルに直接接続するデバッグ体験
desired_countを変更するだけのシンプルなスケーリング体験
この記事は CDK + Auto Scaling Group ハンズオン(cdk-asg-webapp) の発展記事です。
cdk-asg-webapp を体験済みの方向けです(cdk-webapp-pipeline 完了でも OK)。コード詳細は GitHub を参照してください。
-->
キーワード解説
| 用語 | 意味 |
|---|---|
| Docker / Dockerfile | アプリとその実行環境をひとまとめにした「コンテナ」を作成する仕組み。Dockerfile にビルド手順を記述する |
| マルチステージビルド | ビルド環境(Maven)と実行環境(Tomcat)を分離して軽量なイメージを作成するテクニック |
| ECR(Elastic Container Registry) | Docker イメージを保管する AWS マネージドレジストリ。EC2 構成での S3 バケットに相当する |
| ECS Fargate | EC2 なしでコンテナを実行できるサーバーレス実行環境。OS 管理・パッチ適用が不要 |
| タスク定義 | コンテナの CPU・メモリ・環境変数・IAM ロールなどを定義する設定 |
| ECS Service | タスクのスケーリング・ヘルスチェック・ALB 連携・ローリングデプロイを管理する |
| ローリングデプロイ | 旧コンテナを停止しながら新コンテナを順次起動する無停止デプロイ |
| ECS Exec | コンテナ内のシェルに AWS CLI から直接アクセスするデバッグ機能。EC2 の SSM Session Manager に相当 |
| OIDC 認証 | アクセスキーをリポジトリに保存せず、GitHub Actions から AWS を操作できるキーレス認証 |
| インフラ/アプリ分離デプロイ | CDK Pipelines(インフラ)と GitHub Actions(アプリ)で役割を分担する実務パターン |
cdk-asg-webapp との比較
| 比較項目 | cdk-asg-webapp | cdk-ecs-webapp |
|---|---|---|
| 実行環境 | EC2(Launch Template + ASG) | ECS Fargate(サーバーレスコンテナ) |
| デプロイ形式 | WAR → S3 → CodeDeploy | Docker Image → ECR → ECS タスク更新 |
| インフラ管理 | EC2 OS パッチ・エージェント管理が必要 | サーバーレス(EC2 管理不要) |
| スケーリング | CPU 自動スケール(ASG ポリシー) | desired_count を直接変更(シンプル) |
| デバッグ接続 | SSM Session Manager(EC2 に接続) | ECS Exec(コンテナに直接接続) |
| アプリ設定ファイル | appspec.yml + scripts/ | Dockerfile のみ |
| アプリデプロイ担当 | CDK Pipelines 内の CodeDeploy | GitHub Actions |
ファイル構成と役割
cdk-ecs-webapp/
├── app.py ← CDK アプリ エントリポイント
├── cdk.json ← CDK 設定(asg_* → task_cpu / task_memory / desired_count)
├── Dockerfile ← NEW: コンテナイメージのビルド手順(cdk-asg-webapp にはない)
├── app/ ← Spring Boot Webアプリ(Java)
├── pipeline/
│ └── pipeline_stack.py ← CodePipeline(インフラのみ / アプリは GitHub Actions が担当)
├── stages/
│ └── deploy_stage.py ← Stage(WebappStack を内包)
├── stacks/
│ └── webapp_stack.py ← インフラスタック(ECR/ECS の名前を CfnOutput で公開)
└── components/
└── webapp_construct.py ← ECS Fargate ベースの L3 Construct| ファイル | cdk-asg-webapp との主な違い |
|---|---|
Dockerfile | 新規追加。マルチステージビルドで Maven → WAR → Tomcat コンテナを作成 |
webapp_construct.py | AutoScalingGroup + LaunchTemplate → FargateService + TaskDefinition + ECR |
webapp_stack.py | ASGName 等の出力を廃止 → ECRRepoUri / ECSClusterName / ECSServiceName を追加 |
pipeline_stack.py | BuildAndDeployApp(CodeDeploy)を廃止 → インフラ変更のみ担当 |
詳細なコードは GitHub を参照してください。
使用するAWSサービス
| サービス | 役割 | 料金 |
|---|---|---|
| VPC | カスタムネットワーク空間 | 無料 |
| ECS Fargate(0.25 vCPU / 512 MiB) | Spring Boot コンテナを実行するサーバーレス環境 | 約$0.01/時間(無料枠なし) |
| RDS MySQL(db.t3.micro) | マネージドDBサーバ | 月750時間まで無料枠あり |
| ALB | ロードバランサー | 約$0.008/時間 + LCU料金(無料枠なし) |
| ECR | Docker イメージの保管場所 | 500MB/月まで無料 |
| CodePipeline | CI/CD パイプライン管理(インフラ側) | 月1パイプラインまで無料枠あり |
| CodeBuild | cdk synth を実行するビルド環境 | 月100分まで無料枠あり |
| S3 | パイプラインのアーティファクト置き場 | 無料枠あり |
| SSM Parameter Store | DBパスワードの安全な管理・ECS への環境変数注入 | スタンダード層無料 |
| CloudWatch Logs | コンテナのログ出力先 | 無料枠あり |
| IAM | 各サービスの権限 | 無料 |
注意: ECS Fargate と ALB は無料枠がありません。ハンズオン後は必ずリソースを削除してください。
前提条件
| ツール | 確認コマンド |
|---|---|
| AWS CLI v2 | aws --version |
| Java 17 | java -version |
| Maven | mvn -version |
| Python 3.9 以上 | python --version |
| Node.js 18 以上 | node --version |
| CDK CLI | cdk --version |
| Git | git --version |
Docker Desktop は不要です。コンテナのビルドは GitHub Actions runner 上(Ubuntu)で実行されるため、ローカル PC に Docker をインストールする必要はありません。
AWS 認証確認:
aws sts get-caller-identityCDK Bootstrap 確認:
aws cloudformation describe-stacks ^
--stack-name CDKToolkit ^
--query "Stacks[0].StackStatus" ^
--output text ^
--region ap-northeast-1作業順序
① プロジェクトのセットアップ(Python 仮想環境)
↓
② GitHub との接続を設定する(CodeConnections)
↓
③ cdk.json の設定
↓
④ コードを GitHub にプッシュする(重要!)
↓
⑤ パイプラインスタックのデプロイ(初回のみ手動)
↓
⑥ パイプラインの実行状況を確認する
↓
⑦ インフラを確認する
↓
⑧ GitHub Actions を設定する(OIDC + IAM ロール)
↓
⑨ アプリを初回デプロイする
↓
⑩ ECS Exec でコンテナに接続する
↓
⑪ タスク数スケーリングを体験する
↓
⑫ リソースを削除する① プロジェクトのセットアップ
cd C:\my-aws\aws-learning-projects\cdk-ecs-webapp
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txtプロンプトの先頭に (.venv) が表示されれば仮想環境が有効になっています。
重要: CDK コマンドはすべてこの仮想環境が有効な状態で実行する必要があります。
ターミナルを開き直した際は必ず最初に以下を実行してください。cd C:\my-aws\aws-learning-projects\cdk-ecs-webapp .venv\Scripts\activate
② GitHub との接続を設定する(CodeConnections)
cdk-asg-webapp(または cdk-webapp-pipeline)を実施済みの場合: 同じリポジトリを扱うため、
既存の接続(my-github-connection)をそのまま再利用できます。
② はスキップして、ARN の確認(②-4)から始めてください。
CodePipeline が GitHub リポジトリを監視するために、GitHub との接続(CodeConnections) を作成します。
重要: AWS コンソールと GitHub の操作は同じブラウザで行ってください。
接続を作成する
- AWS コンソール検索(
Alt+S)でCodePipelineと入力 → CodePipeline を開く - 左サイドバー → 「設定」 → 「接続」
- リージョンが 東京(ap-northeast-1) になっていることを確認する
- 「接続を作成」をクリック
- プロバイダー: GitHub を選択
- 接続名:
my-github-connection(任意) - 「GitHub に接続する」をクリック
GitHub App をインストールする
- 「Authorize」をクリック → AWS コンソールの「GitHub 接続設定」画面に自動で戻る
- 「新しいアプリをインストールする」をクリック
- 「Only select repositories」 を選択 →
aws-learning-projectsを追加 - 「Install & Authorize」をクリック
- AWS コンソールに自動でリダイレクトされる → 「接続」ボタンをクリック
接続 ARN を確認する
接続一覧から接続の ARN をコピーします。
arn:aws:codeconnections:ap-northeast-1:123456789012:connection/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxステータスが 「利用可能」 になっていることを確認してから次に進んでください。
控えておく情報: 接続 ARN(arn:aws:codeconnections:...)
③ cdk.json の設定
cdk.json の context セクションを自分の環境に合わせて編集します。
{
"context": {
"employee_id": "my",
"db_password": "Handson1234!",
"task_cpu": 256,
"task_memory": 512,
"desired_count": 1,
"github_owner": "your-github-username",
"github_repo": "aws-learning-projects",
"github_branch": "main",
"connection_arn": "arn:aws:codeconnections:ap-northeast-1:..."
}
}| 設定項目 | 値 | 説明 |
|---|---|---|
employee_id | my | リソース名のプレフィックス(my-cdk6-xxx という名前になる) |
task_cpu | 256 | Fargate タスクの CPU ユニット(256 = 0.25 vCPU) |
task_memory | 512 | Fargate タスクのメモリ(MiB) |
desired_count | 1 | ECS サービスの起動タスク数 |
github_owner | GitHub ユーザー名 | リポジトリのオーナー名 |
connection_arn | ②で確認した ARN | CodeConnections の接続 ARN |
task_cpuとtask_memoryの組み合わせ制限(Fargate の仕様)
CPU と Memory には決まった組み合わせがあります。256 CPU の場合、Memory は 512〜2048(512 単位)が有効です。
④ コードを GitHub にプッシュする(重要!)
cdk deployの前に必ずプロジェクト全体を push してください。
パイプラインがcdk synthを実行する際、GitHub から取得したコードを使うためです。
cd C:\my-aws\aws-learning-projects
git add cdk-ecs-webapp/
git commit -m "feat: cdk-ecs-webapp ハンズオンを追加"
git push origin mainGitHub Actions も同時に起動する場合:
app/またはDockerfileの変更が含まれていると GitHub Actions(Deploy App to ECS)も起動しますが、この時点では ECS サービスがまだ存在しないため失敗します。インフラが完成してから ⑨ で改めてアプリをデプロイします。
⑤ パイプラインスタックのデプロイ(初回のみ)
cd C:\my-aws\aws-learning-projects\cdk-ecs-webapp
.venv\Scripts\activate
cdk synth
cdk deploy「Do you wish to deploy these changes?」に y を入力します。
my-EcsPipelineStack が作成され、以降は GitHub push で自動デプロイされます。
所要時間: パイプラインスタック自体のデプロイは 3〜5 分。その後パイプラインが自動起動します。
デプロイ完了後、CodePipeline が自動起動します:
| ステージ | 内容 | 所要時間 |
|---|---|---|
| Source | GitHub から最新コードを取得 | 〜1分 |
| Build (Synth) | cdk synth でテンプレート生成 | 〜3分 |
| UpdatePipeline | パイプライン自己更新(セルフミューテーション) | 〜2分 |
| Deploy > InfraDeploy | CloudFormation で VPC / ECR / ECS / RDS / ALB を構築 | 〜20分 |
初回の InfraDeploy に 20 分程度かかる理由: RDS の起動と ECS サービスの安定化(プレースホルダーコンテナの起動確認)に時間がかかります。
⑥ パイプラインの実行状況を確認する
- AWS コンソール → CodePipeline を開く
my-cdk6-pipelineを選択- 各ステージが 「成功」 になるまで待つ
CloudFormation スタックの命名規則
| 要素 | このハンズオンでの値 |
|---|---|
| パイプラインスタック | my-EcsPipelineStack |
| インフラスタック | my-Deploy-WebappStack |
my-EcsPipelineStack(パイプライン)とmy-Deploy-WebappStack(インフラ)の 2つが別スタックとして CloudFormation に表示されます。
CloudFormation Outputs の確認
aws cloudformation describe-stacks ^
--stack-name my-Deploy-WebappStack ^
--region ap-northeast-1 ^
--query "Stacks[0].Outputs"控えておく情報: ALBEndpoint、RDSEndpoint
⑦ インフラを確認する
ALB の URL を確認する
ALBEndpoint の URL にブラウザでアクセスします。
aws cloudformation describe-stacks ^
--stack-name my-Deploy-WebappStack ^
--region ap-northeast-1 ^
--query "Stacks[0].Outputs[?OutputKey=='ALBEndpoint'].OutputValue" ^
--output textこの時点では Tomcat のデフォルト画面(または 404)が表示されます。
ECS タスクがプレースホルダーイメージ(公式 Tomcat)で起動しているためで、正常な状態です。
Spring Boot アプリのデプロイは ⑨ で実施します。
ECS コンソールで確認する
ECS → クラスター → my-cdk6-cluster → サービス → my-cdk6-service
「タスク」タブで 1 タスクが RUNNING になっていることを確認します。
「タスク定義」タブでリビジョンが 1(プレースホルダー)になっていることを確認します。
⑧ GitHub Actions を設定する(OIDC + IAM ロール)
Spring Boot アプリのデプロイを担う GitHub Actions を設定します。
OIDC 認証によりアクセスキーをリポジトリに保存せずに AWS を操作できます。
OIDC プロバイダーを登録する
AWS コンソール → IAM → 左メニュー「IDプロバイダー」→「プロバイダーを追加」
| 項目 | 値 |
|---|---|
| プロバイダータイプ | OpenID Connect |
| プロバイダー URL | https://token.actions.githubusercontent.com |
| 対象者(Audience) | sts.amazonaws.com |
「プロバイダーを追加」ボタンをクリックして完了。
URL と対象者を入力するだけでよいです(現在の UI ではサムプリントの手動取得は不要)。
IAM ロールを作成する(CloudShell)
AWS コンソール → 右上「CloudShell」アイコン → 以下を貼り付けて実行します。GITHUB_OWNER を自分の GitHub ユーザー名に変更してください:
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
GITHUB_OWNER="your-github-username" # ← 自分の GitHub ユーザー名に変更
REPO="aws-learning-projects"
ROLE_NAME="my-github-actions-role"
cat > /tmp/trust-policy.json << EOF
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::${ACCOUNT_ID}:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:${GITHUB_OWNER}/${REPO}:ref:refs/heads/main"
}
}
}]
}
EOF
aws iam create-role \
--role-name $ROLE_NAME \
--assume-role-policy-document file:///tmp/trust-policy.json
# 権限ポリシーを作成(ECR push + ECS deploy に必要な最小権限)
cat > /tmp/permissions.json << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["ecr:GetAuthorizationToken"],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ecr:BatchCheckLayerAvailability", "ecr:PutImage",
"ecr:InitiateLayerUpload", "ecr:UploadLayerPart", "ecr:CompleteLayerUpload"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ecs:DescribeTaskDefinition", "ecs:RegisterTaskDefinition",
"ecs:UpdateService", "ecs:DescribeServices"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": ["iam:PassRole"],
"Resource": "*"
}
]
}
EOF
aws iam put-role-policy \
--role-name $ROLE_NAME \
--policy-name "${ROLE_NAME}-policy" \
--policy-document file:///tmp/permissions.json
echo "=== Role ARN(次の手順でコピー)==="
aws iam get-role --role-name $ROLE_NAME --query Role.Arn --output text出力された ロール ARN(arn:aws:iam::...)をコピーしておきます。
GitHub Variables を設定する
GitHub リポジトリ → Settings → Secrets and variables → Actions → 「Variables」タブ
「New repository variable」で以下の2つを追加します:
| Name | Value |
|---|---|
EMPLOYEE_ID | my(cdk.json の employee_id と同じ値) |
AWS_ROLE_ARN | IAM ロール作成で表示された ARN |
Variables と Secrets の使い分け: ARN や EMPLOYEE_ID は機密情報ではないため Variables に保存します(Secrets は使いません)。
ワークフローファイルを push する
.github/workflows/ecs-app-deploy.yml は既にリポジトリに含まれています。
このファイルを push してワークフローをアクティブにします:
cd C:\my-aws\aws-learning-projects
git add .github/workflows/ecs-app-deploy.yml
git commit -m "feat: add GitHub Actions ECS deploy workflow"
git pushこのワークフローは
pathsフィルターによりapp/かDockerfileが変わった時だけ起動します。
このコミットでは GitHub Actions はスキップされ、CDK Pipelines のみが起動(インフラ差分なしで数分で完了)します。
⑨ アプリを初回デプロイする(GitHub Actions)
GitHub Actions の設定が完了したので、Spring Boot アプリを ECS に初めてデプロイします。
アプリのタイトルを変更する
cdk-ecs-webapp/app/src/main/resources/templates/index.html を開き、以下の行を変更します:
変更前:
<h1>Spring Boot + RDS Item Manager (ECS)</h1>変更後:
<h1>Spring Boot + RDS Item Manager (ECS v2)</h1>コミット&プッシュ
cd C:\my-aws\aws-learning-projects
git add cdk-ecs-webapp/app/src/main/resources/templates/index.html
git commit -m "feat: initial app deploy via GitHub Actions"
git pushapp/ の変更のため、GitHub Actions が起動します(CDK Pipelines も起動しますがインフラ差分なしで数分で完了)。
GitHub Actions の進行を確認する
GitHub リポジトリ → Actions タブ → Deploy App to ECS ワークフローの進行を確認します。
| ステップ | 内容 | 時間目安 |
|---|---|---|
| Checkout | コード取得 | 〜10秒 |
| Configure AWS credentials | OIDC 認証 | 〜10秒 |
| Login to ECR | ECR ログイン | 〜10秒 |
| Build and push | docker build + ECR push | 〜1〜2分 |
| Update ECS task definition | タスク定義を新リビジョンに更新 | 〜10秒 |
| Deploy to ECS | サービス更新 + 安定化待ち | 〜2〜3分 |
ブラウザで動作確認する
Deploy to ECS ステップが完了したら、ALB の URL にアクセスします。
「Spring Boot + RDS Item Manager (ECS v2)」の画面が表示されることを確認します。
ECS コンソールで確認: ECS → サービス → 「タスク」タブ
タスク定義のリビジョンが 2 以上(GitHub Actions による更新後)になっていることを確認します。
⑩ ECS Exec でコンテナに接続する
cdk-asg-webapp では SSM Session Manager で EC2 に接続しましたが、ECS Fargate では ECS Exec でコンテナ内のシェルに直接接続できます。
実行中のタスク ARN を確認する
aws ecs list-tasks ^
--cluster my-cdk6-cluster ^
--service-name my-cdk6-service ^
--desired-status RUNNING ^
--region ap-northeast-1 ^
--query "taskArns" ^
--output text出力例:
arn:aws:ecs:ap-northeast-1:123456789012:task/my-cdk6-cluster/abcdef1234567890複数件表示される場合: ローリングデプロイ中は新旧2タスクが同時に動きます。
ECS コンソール → サービス → 「タスク」タブでリビジョン番号が大きい方(最新)の ARN を使ってください。
コンテナに接続する
aws ecs execute-command ^
--cluster my-cdk6-cluster ^
--task arn:aws:ecs:ap-northeast-1:123456789012:task/my-cdk6-cluster/abcdef1234567890 ^
--container my-cdk6-app ^
--interactive ^
--command "/bin/sh" ^
--region ap-northeast-1Session Manager Plugin が必要: 接続には AWS CLI の Session Manager Plugin が必要です。
インストール手順は AWS 公式ドキュメント を参照してください。
コンテナ内で確認する
# 環境変数(DB接続情報)を確認
echo $DB_HOST
echo $DB_PASSWORD
# デプロイされた WAR を確認(ROOT.war として配置される)
ls /usr/local/tomcat/webapps/
# 接続を終了
exit
catalina.outは存在しません: Docker コンテナの Tomcat はファイルにログを書かず、stdout(標準出力) に直接出力します。ログは CloudWatch Logs に転送されます。aws logs tail /ecs/my-cdk6-app ^ --follow ^ --region ap-northeast-1終了は
Ctrl+C。
⑪ タスク数スケーリングを体験する
cdk-asg-webapp では stress-ng で CPU 負荷をかけて自動スケールを体験しましたが、
ECS Fargate では desired_count を直接変更するだけでスケールできます。
スケールアウト(1台 → 2台)
aws ecs update-service ^
--cluster my-cdk6-cluster ^
--service my-cdk6-service ^
--desired-count 2 ^
--region ap-northeast-1ECS コンソール → サービス → 「タスク」タブで 2 タスクが RUNNING になることを確認します。
ALB がどちらのタスクにもリクエストを分散するようになります(ラウンドロビン)。
スケールイン(2台 → 1台)
aws ecs update-service ^
--cluster my-cdk6-cluster ^
--service my-cdk6-service ^
--desired-count 1 ^
--region ap-northeast-1数分後に 1 タスクが停止し、1 台構成に戻ります。
ECS と ASG のスケーリング比較
- ECS:
desired_countを変更するだけ(コマンド一発、秒単位で反映)- ASG: CPU 閾値・CloudWatch アラーム・スケーリングポリシーが必要(設定が複雑)
ECS Fargate はコンテナ単位なので起動が速く(30秒〜)、EC2 の起動を待つ ASG より素早くスケールできます。
⑫ リソースを削除する
課金を止めるために、ハンズオン完了後は必ず削除します。
削除順序が重要です。インフラスタック(
my-Deploy-WebappStack)を先に削除してから、パイプラインスタック(my-EcsPipelineStack)を削除します。
1. インフラスタックを削除する
aws cloudformation delete-stack ^
--stack-name my-Deploy-WebappStack ^
--region ap-northeast-1
aws cloudformation wait stack-delete-complete ^
--stack-name my-Deploy-WebappStack ^
--region ap-northeast-1
echo WebappStack 削除完了RDS の削除に 10〜15 分かかります。
waitコマンドが完了するまでそのまま待ってください。
2. パイプラインスタックを削除する
aws cloudformation delete-stack ^
--stack-name my-EcsPipelineStack ^
--region ap-northeast-1
aws cloudformation wait stack-delete-complete ^
--stack-name my-EcsPipelineStack ^
--region ap-northeast-1
echo EcsPipelineStack 削除完了3. GitHub Actions IAM ロールを削除する
CloudFormation の管理外のため、手動で削除します:
aws iam delete-role-policy ^
--role-name my-github-actions-role ^
--policy-name my-github-actions-role-policy
aws iam delete-role ^
--role-name my-github-actions-role4. SSM パラメータを削除する
aws ssm delete-parameter ^
--name "/my/cdk6/db-password" ^
--region ap-northeast-15. 仮想環境の終了
deactivate6. GitHub との接続を削除する(オプション)
次のハンズオンでも使う場合はそのままでよいです。
CodePipeline → 設定 → 接続 → my-github-connection → 「削除」
7. OIDC プロバイダーを削除する(オプション)
他のリポジトリでも使う場合はそのままでよいです。
不要な場合は IAM → IDプロバイダー → token.actions.githubusercontent.com → 「削除」
削除確認
aws cloudformation list-stacks ^
--region ap-northeast-1 ^
--stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE ^
--query "StackSummaries[?contains(StackName, 'my-')].StackName"空のリスト [] が返れば削除完了です。
EC2 → コンテナへの移行ポイント
cdk-asg-webapp(EC2 + ASG) cdk-ecs-webapp(ECS Fargate)
───────────────────────────── ─────────────────────────────
Launch Template Dockerfile
↓ UserData(シェルスクリプト) ↓ マルチステージビルド(20行)
Java インストール Maven → WAR → Tomcat(イメージ内)
Tomcat インストール
CodeDeploy エージェントインストール
↓ ↓
appspec.yml + scripts/*.sh Dockerfile のみ
S3 → CodeDeploy → WAR デプロイ ECR → ECS タスク更新 → ローリングデプロイ
↓ ↓
SSM Session Manager(EC2 に接続) ECS Exec(コンテナに直接接続)
↓ ↓
CPU 自動スケール(ASG ポリシー) desired_count を変更(コマンド一発)appspec.yml / scripts/*.sh / UserData の複雑な設定が、Dockerfile の 20 行に集約されます。
トラブルシューティング
| 症状 | 原因 | 対処 |
|---|---|---|
Source ステージが「失敗」 | GitHub との接続が「保留中」 | CodePipeline → 設定 → 接続 → 承認して「利用可能」にする |
ECS タスクが STOPPED を繰り返す | プレースホルダーイメージの pull 失敗 | ECS コンソール → 停止タスク → 「停止理由」を確認 |
| GitHub Actions が失敗(OIDC エラー) | IAM ロールの信頼ポリシーが不正 | GitHub Variables の AWS_ROLE_ARN と信頼ポリシーの sub を確認 |
| GitHub Actions が失敗(ECR push) | ecr:GetAuthorizationToken 権限不足 | IAM ロールのポリシーを確認 |
| アプリ画面が表示されない(404) | GitHub Actions がまだ実行されていない | Actions タブで Deploy App to ECS が完了するまで待つ |
| ECS Exec が接続できない | enable_execute_command が未設定 | ECS サービスの設定を確認(CDK で有効化済み) |
Session Manager Plugin is not found | Plugin 未インストール | AWS 公式ドキュメントからインストール |
| RDS 接続エラー | DB_HOST / DB_PASSWORD が不正 | CloudWatch Logs → /ecs/my-cdk6-app でログを確認 |
まとめ
| ステップ | 内容 |
|---|---|
| ① | Python 仮想環境のセットアップ |
| ② | CodeConnections で GitHub との接続を作成(cdk-asg-webapp 実施済みなら再利用) |
| ③ | cdk.json を設定(task_cpu / task_memory / desired_count) |
| ④ | cdk-ecs-webapp/ 全体を GitHub に push |
| ⑤ | cdk deploy(初回のみ手動)→ my-EcsPipelineStack 作成 |
| ⑥ | CodePipeline → my-cdk6-pipeline が自動起動 → InfraDeploy(20分)完了まで待つ |
| ⑦ | ALB URL にアクセス(Tomcat のデフォルト画面)・ECS サービスが RUNNING を確認 |
| ⑧ | OIDC プロバイダー登録 → IAM ロール作成 → GitHub Variables 設定 → workflow push |
| ⑨ | app/index.html を変更して push → GitHub Actions が Docker build → ECR push → ECS deploy |
| ⑩ | ecs execute-command でコンテナ内シェルに接続・環境変数や WAR を確認 |
| ⑪ | update-service --desired-count 2 でスケールアウト → 1 に戻してスケールイン |
| ⑫ | delete-stack my-Deploy-WebappStack → delete-stack my-EcsPipelineStack → IAM ロール・SSM 削除 |
EC2 + CodeDeploy から ECS Fargate + GitHub Actions への移行で、EC2 の OS 管理・エージェント管理から解放され、Dockerfile 1ファイルにデプロイ設定が集約されることを体験できました。
コンソールで3層構成を視覚的に学びたい場合は AWSコンソール版ハンズオン、CDK の基本は CDK版ハンズオン(cdk-alb-ec2-rds)、インフラ CI/CD は CDK Pipelines ハンズオン、アプリ CI/CD は CDK + CodeDeploy ハンズオン、ASG でのオートスケーリングは CDK + ASG ハンズオン を参照してください。
コメント