Claude Code × AWS ECS/Fargate 完全ガイド|コンテナデプロイを自動化する
AWS ECS/FargateへのデプロイをClaude Codeで自動化。タスク定義・サービス設定・Blue/Greenデプロイ・CDKでのインフラ構築まで、Masaの実務経験をもとに解説。
「コンテナをAWSで動かしたいけど、ECSの設定が複雑すぎる」——これは多くのエンジニアが最初にぶつかる壁です。タスク定義・サービス・クラスター・ロードバランサー・オートスケーリング……設定項目が多すぎて、どこから手をつければいいかわからない。
私は業務でECS/Fargateを使ったサーバーレスコンテナ環境を構築していますが、Claude Code に構成を伝えるだけでタスク定義からCDKコードまで一式生成できるようになってから、デプロイ作業が格段に楽になりました。この記事では、その実践手順を解説します。
ECS/Fargate の基礎を3分で整理
クラスター: ECSコンテナが動く「箱」
タスク定義: コンテナの設定仕様書 (イメージ・CPU・メモリ・環境変数)
サービス: タスクを何台起動するかの設定 (オートスケーリング含む)
Fargate: サーバー管理不要のコンテナ実行エンジン
EC2と違い、Fargateはサーバーのプロビジョニング・パッチ適用が不要。コンテナの設定に集中できます。
Step 1: タスク定義を自動生成
claude -p "
以下の条件で ECS タスク定義を JSON で生成して。
- アプリ: Node.js API (ポート3000)
- CPU: 512 (0.5 vCPU)
- メモリ: 1024 MB
- 環境変数: DATABASE_URL (Secrets Manager から取得), NODE_ENV=production
- ログ: CloudWatch Logs (ロググループ /ecs/myapp)
- ヘルスチェック: /health エンドポイント、30秒間隔
- コンテナイメージ: 123456789.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:latest
- 実行ロール: ecsTaskExecutionRole
- タスクロール: myapp-task-role (DynamoDB・S3へのアクセス権)
"
生成されるタスク定義:
{
"family": "myapp-task",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "512",
"memory": "1024",
"executionRoleArn": "arn:aws:iam::123456789:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::123456789:role/myapp-task-role",
"containerDefinitions": [
{
"name": "myapp",
"image": "123456789.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:latest",
"portMappings": [{ "containerPort": 3000, "protocol": "tcp" }],
"environment": [{ "name": "NODE_ENV", "value": "production" }],
"secrets": [
{
"name": "DATABASE_URL",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789:secret:prod/database-url"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/myapp",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
}
},
"healthCheck": {
"command": ["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"],
"interval": 30,
"timeout": 5,
"retries": 3,
"startPeriod": 60
}
}
]
}
Step 2: CDKでECS/Fargate環境を構築
タスク定義だけでなく、クラスター・サービス・ALBまで一括でCDK化します。
claude -p "
lib/ecs-stack.ts に以下の ECS/Fargate 環境を CDK TypeScript で実装して。
- VPC: 既存のVPCをimport (vpcId を環境変数から取得)
- ECSクラスター: Fargate のみ
- タスク定義: 上で生成したものと同仕様
- ALB: HTTPS (ACM証明書 ARN を環境変数から取得)、HTTPは301リダイレクト
- サービス: 最小2台、最大10台のオートスケーリング
- CPU使用率70%でスケールアウト
- ターゲット追跡スケーリング
- Blue/Greenデプロイ対応 (CodeDeploy連携)
- サービスの稼働状態を CloudWatch ダッシュボードに表示
"
// lib/ecs-stack.ts
import * as cdk from "aws-cdk-lib";
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as ecs from "aws-cdk-lib/aws-ecs";
import * as ecsp from "aws-cdk-lib/aws-ecs-patterns";
import * as acm from "aws-cdk-lib/aws-certificatemanager";
export class EcsStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// 既存VPCをimport
const vpc = ec2.Vpc.fromLookup(this, "Vpc", {
vpcId: process.env.VPC_ID!,
});
// ECSクラスター
const cluster = new ecs.Cluster(this, "Cluster", {
vpc,
clusterName: "myapp-cluster",
containerInsights: true, // CloudWatch Container Insights有効
});
// ACM証明書
const certificate = acm.Certificate.fromCertificateArn(
this, "Certificate",
process.env.CERTIFICATE_ARN!
);
// タスク定義
const taskDef = new ecs.FargateTaskDefinition(this, "TaskDef", {
cpu: 512,
memoryLimitMiB: 1024,
});
const container = taskDef.addContainer("app", {
image: ecs.ContainerImage.fromEcrRepository(
ecr.Repository.fromRepositoryName(this, "Repo", "myapp")
),
environment: { NODE_ENV: "production" },
logging: ecs.LogDrivers.awsLogs({ streamPrefix: "ecs" }),
healthCheck: {
command: ["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"],
interval: cdk.Duration.seconds(30),
timeout: cdk.Duration.seconds(5),
retries: 3,
startPeriod: cdk.Duration.seconds(60),
},
});
container.addPortMappings({ containerPort: 3000 });
// ALB + Fargate サービス (パターンを使って簡潔に)
const service = new ecsp.ApplicationLoadBalancedFargateService(
this, "Service", {
cluster,
taskDefinition: taskDef,
desiredCount: 2,
certificate,
redirectHTTP: true,
publicLoadBalancer: true,
}
);
// オートスケーリング設定
const scaling = service.service.autoScaleTaskCount({
minCapacity: 2,
maxCapacity: 10,
});
scaling.scaleOnCpuUtilization("CpuScaling", {
targetUtilizationPercent: 70,
scaleInCooldown: cdk.Duration.seconds(60),
scaleOutCooldown: cdk.Duration.seconds(60),
});
// Output
new cdk.CfnOutput(this, "LoadBalancerDns", {
value: service.loadBalancer.loadBalancerDnsName,
});
}
}
Step 3: GitHub ActionsでCI/CDパイプラインを構築
claude -p "
GitHub Actions で以下のCI/CDパイプラインを作成して:
1. main ブランチへの push をトリガー
2. Dockerイメージをビルドして ECR にプッシュ
3. ECS タスク定義の image タグを新しいSHAに更新
4. ECS サービスに新しいタスク定義をデプロイ
5. デプロイ完了をSlackに通知
環境: ap-northeast-1、ECR リポジトリ名: myapp
"
name: Deploy to ECS
on:
push:
branches: [main]
env:
AWS_REGION: ap-northeast-1
ECR_REPOSITORY: myapp
ECS_CLUSTER: myapp-cluster
ECS_SERVICE: myapp-service
CONTAINER_NAME: app
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
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: Build, tag, and push image to ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
- name: Download task definition
run: |
aws ecs describe-task-definition --task-definition myapp-task \
--query taskDefinition > task-definition.json
- name: Update ECS task definition with new image
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: task-definition.json
container-name: ${{ env.CONTAINER_NAME }}
image: ${{ steps.build-image.outputs.image }}
- name: Deploy to ECS
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: true
- name: Notify Slack on success
if: success()
uses: slackapi/slack-github-action@v1
with:
webhook: ${{ secrets.SLACK_WEBHOOK }}
payload: |
{"text": "✅ Deployed to ECS: ${{ github.sha }}"}
Step 4: Blue/Greenデプロイの設定
claude -p "
ECS サービスで Blue/Green デプロイ (CodeDeploy) を設定するための
CDK コードと AppSpec ファイルを生成して。
ロールバック条件: デプロイ後5分以内に CloudWatch アラームが発火したら自動ロールバック
"
# appspec.yaml (CodeDeploy用)
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: <TASK_DEFINITION>
LoadBalancerInfo:
ContainerName: app
ContainerPort: 3000
PlatformVersion: LATEST
Hooks:
- BeforeAllowTraffic: "arn:aws:lambda:ap-northeast-1:123456789:function:health-check"
- AfterAllowTraffic: "arn:aws:lambda:ap-northeast-1:123456789:function:smoke-test"
落とし穴5選
1. ヘルスチェックの startPeriod を忘れる
Fargateコンテナは起動直後にヘルスチェックが走りますが、アプリの起動が遅いと即UNHEALTHYになります。startPeriod: 60 (秒) を設定してアプリの起動時間を確保しましょう。
2. タスクロールと実行ロールを混同する
executionRole (ecsTaskExecutionRole): コンテナ起動に必要な権限
→ ECR からのイメージ pull、CloudWatch Logs への書き込み
taskRole (myapp-task-role): アプリが使う権限
→ DynamoDB、S3、SQS などへのアクセス
どちらのロールに何を追加するか、よく間違えます。
3. awsvpc ネットワークモードでのセキュリティグループ設定
Fargateは必ず awsvpc ネットワークモードが必要です。コンテナのセキュリティグループをALBからのみに制限するのを忘れると、コンテナが直接外部に公開されます。
4. Secrets Manager の取得に実行ロールが必要
secrets で Secrets Manager の値を取得するには executionRole に secretsmanager:GetSecretValue 権限が必要です。抜け漏れでコンテナが起動しないことがよくあります。
5. デプロイ時の desired_count: 0 問題
オートスケーリングで最小値が0のサービスは、深夜に全コンテナが落ちて朝の起動が遅くなります。最小値は本番で最低2台に設定しましょう。
まとめ
| タスク | Claude Code の貢献 |
|---|---|
| タスク定義生成 | 要件を伝えるだけでJSON完成 |
| CDK実装 | クラスター・サービス・ALB・オートスケーリング一括生成 |
| CI/CD設定 | GitHub Actions ワークフロー生成 |
| Blue/Greenデプロイ | AppSpec・CodeDeploy設定を自動生成 |
| トラブル解決 | エラーログから原因と修正方法を提示 |
ECSは設定項目が多いですが、Claude Code に「こういう構成が欲しい」と伝えるだけで、ベストプラクティスに沿った設定が一式揃います。まずCDKから試すのが一番楽でおすすめです。
関連記事
- Claude Code × AWS Lambda 完全ガイド
- Claude Code × AWS IAM 完全ガイド
- Claude Code × AWS CloudFormation/CDK 完全ガイド
参考資料
無料PDF: Claude Code 5分でわかるチートシート
メールアドレスを登録するだけで、A4 1枚のチートシートPDFを今すぐお送りします。
個人情報は厳重に管理し、スパムは送りません。
この記事を書いた人
Masa
現役DX室長|Claude Code でゼロから多言語AI技術メディア運営中。実務直結の自動化、AI開発相談・研修受付中。
関連書籍・参考図書
この記事のテーマに関連する書籍を楽天ブックスで探せます。
※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。
関連記事
Claude Code × Amazon Bedrock 完全ガイド|AWS上でClaudeを本番運用する
Claude CodeでAmazon Bedrockを活用する完全ガイド。IAM認証・ストリーミング・Lambda統合・RAG実装・コスト最適化まで、Masaの業務実装経験をもとに解説。
Claude Code × AWS CodePipeline/CodeBuild 完全ガイド|CI/CDパイプラインを自動構築
AWS CodePipeline・CodeBuildによるCI/CDをClaude Codeで自動構築。パイプライン設計・buildspec.yml生成・テスト自動化・CDKでのインフラ定義まで実例コードで解説。
Claude Code × AWS CloudWatch 完全ガイド|ログ分析・アラーム設定・ダッシュボード自動構築
AWS CloudWatchをClaude Codeで効率化。ログのパターン分析・アラーム自動設定・メトリクスダッシュボード構築・インシデント調査まで実例コードで解説。