📑 目次
🍔 フードトラックの「営業しながらメニュー刷新」で例えると超わかりやすい!
ECS Fargateのローリングデプロイ = お店を閉めずにメニューを新しくすること!
フードトラックが4台で営業中。新メニューに切り替えたいけど、
全部同時に閉めたらお客さんが困る...
だから1台ずつ順番にリニューアル!
これをAWSのCodeシリーズで
完全自動化
する方法を
ゼロから本番運用まで
徹底解説します✨
🚚 1. フードトラックチェーンで理解する全体像
AWS用語 ↔ フードトラック用語の対応表
🚚 フードトラック
料理を提供する車両
4台で営業中
🐳 ECSタスク
アプリを実行するコンテナ
4タスクで稼働中
🔄 2. ローリングデプロイの仕組み
📊 タスク数4の場合のデプロイ進行イメージ
→ 一時的に5タスク稼働
→ v1を1つ停止開始
v1: 2台, v2: 2台
ダウンタイムゼロ🎉
⚙️ minimumHealthyPercent: 100%
デプロイ中も
最低100%のタスクを維持
。
つまり、旧タスクを停止する前に必ず新タスクが正常稼働していることを保証。
minimumHealthyPercent = 100
⚙️ maximumPercent: 200%
一時的に
最大200%(2倍)のタスク
を許容。
これにより、新タスクを追加してからヘルスチェック後に旧タスクを停止できる。
maximumPercent = 200
⚖️ 3. デプロイ方式の比較と選択
ECS標準ローリングデプロイ
- CodeDeployが不要 でシンプル
- 追加コストがほぼかからない
- 設定がシンプルで学習コストが低い
- タスクを順次入れ替え
- ロールバックは再デプロイで対応
- 小〜中規模サービスに最適
CodeDeploy Blue/Green
- CodeDeployが必要
- 新環境を完全に構築してから切替
- 瞬時のロールバックが可能
- トラフィック段階的シフト可能
- 一時的に2倍のリソース費用
- 大規模・ミッションクリティカルに最適
🤔 どちらを選ぶべき?判断フローチャート
🔗 CodePipelineの4ステージ構成
mainブランチへのpushで自動トリガー。
ECRにプッシュ、imagedefinitions.json出力。
ローリングデプロイで順次タスク入替。
ダウンタイムゼロでデプロイ完了!
🛠️ 4. 実装ステップバイステップ
前提条件の準備
パイプライン構築前に必要なAWSリソースを準備します。
必要なリソース:
- VPC : パブリック/プライベートサブネット、NAT Gateway
- ALB : ターゲットグループ、リスナー設定
- ECR : コンテナイメージ用リポジトリ
- ECSクラスター : Fargateクラスター
- CloudWatch Logs : ロググループ
- セキュリティグループ : ALB用、タスク用
ソースリポジトリの準備
CodeCommitまたはGitHubにリポジトリを作成し、必要なファイルを配置します。
リポジトリ構成:
-
Dockerfile- コンテナイメージ定義 -
buildspec.yml- CodeBuildの設定 -
taskdef.json- ECSタスク定義(オプション) -
src/- アプリケーションコード
ECSタスク定義の作成
ECSコンソールまたはCLIでタスク定義を作成します。
設定ポイント:
- 起動タイプ: FARGATE
- ネットワークモード: awsvpc
- イメージ: ECRのリポジトリURIを指定
- ログ設定: CloudWatch Logsを設定
ECSサービスの作成
タスク定義を使ってECSサービスを作成します。
重要な設定:
- デプロイタイプ: ローリング更新
- minimumHealthyPercent: 100
- maximumPercent: 200
- ヘルスチェック猶予期間: 60秒〜
- デプロイサーキットブレーカー: 有効
CodeBuildプロジェクトの作成
Dockerイメージをビルドするプロジェクトを作成します。
設定ポイント:
- 環境イメージ: aws/codebuild/amazonlinux2-x86_64-standard:4.0
- 特権モード: 有効 (Docker使用時必須)
- サービスロール: ECRアクセス権限を付与
- 環境変数: AWS_ACCOUNT_ID, IMAGE_REPO_NAME等
CodePipelineの作成
全体を統括するパイプラインを作成します。
ステージ構成:
- Source : CodeCommit/GitHub接続
- Build : CodeBuildプロジェクト指定
- Deploy : Amazon ECSアクション選択、クラスター・サービス指定
📄 5. 設定ファイル完全解説
version: 0.2 phases: pre_build: commands: # ECRにログイン - echo Logging in to Amazon ECR... - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com # イメージタグにコミットハッシュを使用(latestは避ける) - IMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7) - REPOSITORY_URI=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME build: commands: # Dockerイメージをビルド - echo Building the Docker image... - docker build -t $REPOSITORY_URI:$IMAGE_TAG . - docker tag $REPOSITORY_URI:$IMAGE_TAG $REPOSITORY_URI:latest post_build: commands: # ECRにプッシュ - echo Pushing the Docker image... - docker push $REPOSITORY_URI:$IMAGE_TAG - docker push $REPOSITORY_URI:latest # ★重要: imagedefinitions.jsonを出力(CodePipelineのECSデプロイで使用) - printf '[{"name":"my-container","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json - cat imagedefinitions.json artifacts: files: - imagedefinitions.json # ★これが必須!
imagedefinitions.json
は、CodePipelineのECSデプロイアクションが
どのイメージでタスク定義を更新するか
を知るために必須のファイルです。このファイルがないとデプロイが失敗します。
# ベースイメージ FROM node:18-alpine # 作業ディレクトリ WORKDIR /app # 依存関係をインストール COPY package*.json ./ RUN npm ci --only=production # アプリケーションコードをコピー COPY . . # ヘルスチェック用エンドポイント HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1 # ポート公開 EXPOSE 3000 # アプリケーション起動 CMD ["node", "server.js"]
// ECS標準デプロイで使用する形式 [ { "name": "my-container", // タスク定義のコンテナ名と一致させる "imageUri": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/my-app:abc1234" } ]
imageDetail.json
(CodeDeploy用)と
imagedefinitions.json
(ECS標準デプロイ用)は
形式が異なります
。今回のローリングデプロイでは
imagedefinitions.json
を使用します。
🔐 6. IAMロール・ポリシー設定
🔨 CodeBuildサービスロール
CodeBuildがECRにプッシュするために必要な権限
🔗 CodePipelineサービスロール
パイプラインが各サービスを操作するために必要
🐳 ECSタスク実行ロール
Fargateがコンテナを起動するために必要
📋 ECSタスクロール(オプション)
コンテナ内のアプリがAWSサービスを使う場合
🔧 7. トラブルシューティング
タスクがPENDING状態のまま起動しない
🔍 原因と対策:
- ECRへのアクセス権限不足 : タスク実行ロールにECR権限があるか確認
- VPCエンドポイント未設定 : プライベートサブネットの場合、ECR/S3/CloudWatch Logsのエンドポイントが必要
- セキュリティグループ : アウトバウンド443が許可されているか確認
ヘルスチェックに失敗し続ける
🔍 原因と対策:
- アプリ起動時間 : healthCheckGracePeriodSecondsを延長(60→120秒など)
- ヘルスチェックパス : ALBのヘルスチェックパスが正しいか確認(/health等)
- ポートマッピング : コンテナポートとターゲットグループのポートが一致しているか
- セキュリティグループ : ALB→タスク間の通信が許可されているか
CodePipelineのDeployステージが失敗
🔍 原因と対策:
-
ファイル名の確認
:
imagedefinitions.json(sが付く)が正しいか - artifacts設定 : buildspec.ymlのartifactsにファイルが含まれているか
- コンテナ名の一致 : imagedefinitions.jsonのnameがタスク定義のコンテナ名と一致しているか
デプロイが終わらない・ロールバックされる
🔍 原因と対策:
- サーキットブレーカー発動 : 新タスクが連続して失敗している
- リソース不足 : CPU/メモリが足りない、Fargateのキャパシティ不足
- ログ確認 : CloudWatch Logsでアプリのエラーを確認
📊 8. 監視・アラート設定
ECSサービスメトリクス
タスクの状態とリソース使用率を監視
監視項目:
- ✓ CPUUtilization(CPU使用率)
- ✓ MemoryUtilization(メモリ使用率)
- ✓ RunningTaskCount(実行中タスク数)
- ✓ DesiredTaskCount(希望タスク数)
ALBメトリクス
ロードバランサーの健全性を監視
監視項目:
- ✓ HealthyHostCount(正常ホスト数)
- ✓ UnHealthyHostCount(異常ホスト数)
- ✓ HTTPCode_Target_5XX_Count
- ✓ TargetResponseTime(レスポンス時間)
パイプライン通知
デプロイ成功/失敗を即座に通知
設定方法:
- ✓ CodePipeline通知ルール作成
- ✓ SNSトピックに連携
- ✓ Slack/Teams/メール通知
- ✓ 失敗時のみ通知も可能
# デプロイ失敗検知アラーム(実行中タスク < 希望タスク) aws cloudwatch put-metric-alarm \ --alarm-name "ECS-RunningTaskCount-Low" \ --alarm-description "Running tasks below desired count" \ --metric-name RunningTaskCount \ --namespace AWS/ECS \ --statistic Average \ --period 60 \ --threshold 2 \ --comparison-operator LessThanThreshold \ --dimensions Name=ClusterName,Value=my-cluster Name=ServiceName,Value=my-service \ --evaluation-periods 2 \ --alarm-actions arn:aws:sns:ap-northeast-1:123456789012:my-alerts # 5xxエラー急増アラーム aws cloudwatch put-metric-alarm \ --alarm-name "ALB-5xxErrors-High" \ --metric-name HTTPCode_Target_5XX_Count \ --namespace AWS/ApplicationELB \ --statistic Sum \ --period 60 \ --threshold 10 \ --comparison-operator GreaterThanThreshold \ --dimensions Name=LoadBalancer,Value=app/my-alb/xxx Name=TargetGroup,Value=targetgroup/my-tg/xxx \ --evaluation-periods 1 \ --alarm-actions arn:aws:sns:ap-northeast-1:123456789012:my-alerts
💰 9. コスト情報
| サービス | 料金体系 | 目安(東京リージョン) |
|---|---|---|
| CodePipeline | パイプライン数 × 月額 | $1/パイプライン/月(最初の1つは無料) |
| CodeBuild | ビルド時間(分単位) |
$0.005/分〜(general1.small)
毎月100分無料 |
| ECR | ストレージ + データ転送 |
$0.10/GB/月
最初の500MB無料 |
| ECS(Fargate) | vCPU + メモリ × 時間 |
vCPU: $0.05056/時間
メモリ: $0.00553/GB/時間 |
| ALB | 時間 + LCU | $0.0243/時間 + LCU使用量 |
💡 コスト最適化のポイント
- ECRライフサイクルポリシー : 古いイメージを自動削除してストレージ費用を削減
- Fargate Spot : 中断可能なワークロードなら最大70%オフ
- 適切なリソースサイジング : CPU/メモリを実際の使用量に合わせて最適化
- ビルドキャッシュ活用 : CodeBuildのキャッシュでビルド時間短縮
🌍 マルチ環境パイプライン構成
✅ デプロイ前チェックリスト
📋 インフラ準備
- VPC、サブネット、NAT Gatewayを作成
- ALB、ターゲットグループを作成
- ECRリポジトリを作成
- ECSクラスターを作成
- CloudWatch Logsグループを作成
- セキュリティグループを適切に設定
🔐 IAM設定
- CodeBuildサービスロールを作成
- CodePipelineサービスロールを作成
- ECSタスク実行ロールを作成
- 必要に応じてタスクロールを作成
- 最小権限の原則に従っているか確認
📝 ソースコード
- Dockerfileが正しく動作する
- buildspec.ymlを配置
- imagedefinitions.jsonが出力される
- ヘルスチェックエンドポイントがある
- 環境変数の設定が適切
⚙️ ECS設定
- タスク定義のコンテナ名を確認
- minimumHealthyPercent: 100
- maximumPercent: 200
- healthCheckGracePeriodを適切に設定
- デプロイサーキットブレーカー有効化
- ログ設定が正しい
❓ よくある質問
[{"name":"コンテナ名","imageUri":"イメージURI"}]
imageDetail.json : CodeDeployを使ったBlue/Greenデプロイで使用。形式は
{"ImageURI":"イメージURI"}
今回のローリングデプロイでは imagedefinitions.json を使用します。
maximumPercent: 200%の設定により、新タスクを先に起動(一時的に2タスク)→ヘルスチェックOK→旧タスク停止、という流れでダウンタイムなしでデプロイできます。
ただし、可用性を考えると本番環境では2タスク以上を推奨します。
無効の場合は、新タスクが起動できず古いタスクが稼働し続けます。
本番環境では必ずサーキットブレーカーを有効にしましょう!
1. CodePipelineコンソールで「設定」→「接続」から新規作成
2. GitHubにOAuth認証でログイン
3. リポジトリへのアクセスを許可
4. パイプラインのSourceステージで作成した接続を選択
Webhook経由でpushを検知し、自動でパイプラインが開始されます。
Blue/Green : ロールバックが瞬時(数秒)。問題発生時の影響を最小化できる。ただし一時的に2倍のリソース費用がかかる。
ローリング : ロールバックは再デプロイ(数分)。コスト効率が良い。サーキットブレーカーで自動ロールバックも可能。
ミッションクリティカルなサービスはBlue/Green、それ以外はローリングがバランスが良いでしょう。
コミットハッシュやビルド番号をタグに使用。どのバージョンがデプロイされたか追跡可能に!
2. ヘルスチェックを正しく実装:
単純な200 OKではなく、DB接続など依存サービスの確認も含めた/healthエンドポイントを実装。
3. healthCheckGracePeriodを十分に取る:
アプリケーションの起動時間 + 余裕を持った値を設定(最低60秒、Spring Bootなどは120秒以上推奨)。
4. デプロイサーキットブレーカーを有効化:
失敗が続いた場合に自動でロールバック。ECSサービス設定で必ず有効化!
5. CloudWatch Logsでコンテナログを収集:
デプロイ失敗時の原因調査に必須。Container Insightsも有効化するとさらに便利。
🎓 まとめ
🚚 フードトラックのリニューアル = ECSローリングデプロイ
CodeシリーズでECS Fargateへの完全自動CI/CDパイプラインを構築!
お客さん(ユーザー)に影響を与えずに
新バージョンをデプロイできます
• minimumHealthyPercent: 100% (常にサービス維持)
• maximumPercent: 200% (新タスク追加を許容)
• デプロイサーキットブレーカー: 有効 (失敗時自動ロールバック)
• 出力ファイル: imagedefinitions.json (これが必須!)
これで ダウンタイムゼロ のローリングデプロイを実現!🎉