GitHub の変更を検知して ECS Fargate に自動デプロイするパイプラインを構築する
このハンズオンでは GitHub へのコードプッシュをトリガーに、AWS CodePipeline が自動的に Docker イメージをビルドして Amazon ECR に保存し、ECS Fargate サービスに新バージョンをデプロイするパイプラインを構築します。
| 項目 | 内容 |
|---|---|
| 対象サービス | CodePipeline、CodeBuild、ECR、ECS Fargate |
| 主な学習内容 | パイプライン構築・buildspec.yml 記述・ECS ローリングデプロイ自動化 |
| 所要時間 | 90〜120 分 |
| 難易度 | ★★★★☆(中〜上級者向け) |
| 前提知識 | Docker・ECS Fargate の基礎(ECS ハンズオン修了推奨) |
| 費用目安 | 約 1〜3 USD(CodeBuild ビルド時間・ECS 稼働時間による) |
AWS は CodeCommit の新規利用を 2024年7月25日に停止しました。このハンズオンでは GitHub を Source として CodePipeline と連携します(AWS CodeStar Connections を使用)。
| リソース | 名前 | 備考 |
|---|---|---|
| ECR リポジトリ | handson-app | Docker イメージ保管 |
| CodeStar Connections | handson-github-connection | GitHub 認証 |
| CodeBuild プロジェクト | handson-build | イメージビルド・プッシュ |
| IAM ロール(CodeBuild) | codebuild-handson-role | ECR/CWL 権限 |
| IAM ロール(CodePipeline) | codepipeline-handson-role | S3/CodeBuild/ECS 操作権限 |
| S3 バケット(アーティファクト) | codepipeline-artifacts-<id> | パイプライン内部で自動作成 |
| CodePipeline | handson-pipeline | 3 ステージ構成 |
ap-northeast-1(東京)このハンズオンは既存の ECS Fargate サービスへのデプロイを前提としています。ECS ハンズオン未実施の場合は先に実施するか、以下の最小構成を用意してください。
handson-ecs-clusterhandson-ecs-servicehandson-appCI/CD パイプラインのソースとなる GitHub リポジトリを用意します。
GitHub で新規リポジトリ handson-app を Public または Private で作成します。
以下の 3 ファイルをリポジトリに追加します。
const http = require('http');
const PORT = process.env.PORT || 3000;
const VERSION = process.env.APP_VERSION || 'v1.0';
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(`Hello from ECS Fargate! Version: ${VERSION}\n`);
});
server.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
FROM node:20-alpine WORKDIR /app COPY app.js . EXPOSE 3000 CMD ["node", "app.js"]
version: 0.2
env:
variables:
AWS_DEFAULT_REGION: ap-northeast-1
IMAGE_REPO_NAME: handson-app
parameter-store:
AWS_ACCOUNT_ID: /handson/aws-account-id
phases:
pre_build:
commands:
- echo Logging in to Amazon ECR...
- ECR_URI=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${IMAGE_REPO_NAME}
- aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $ECR_URI
- IMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
- echo Image tag is $IMAGE_TAG
build:
commands:
- echo Building Docker image...
- docker build -t $ECR_URI:$IMAGE_TAG .
- docker tag $ECR_URI:$IMAGE_TAG $ECR_URI:latest
post_build:
commands:
- echo Pushing Docker image...
- docker push $ECR_URI:$IMAGE_TAG
- docker push $ECR_URI:latest
- echo Writing imagedefinitions.json...
- printf '[{"name":"handson-app","imageUri":"%s"}]' $ECR_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
files: imagedefinitions.json
CodePipeline の ECS デプロイステージが読み込む JSON ファイルです。name はタスク定義内のコンテナ名(ECS ハンズオンでは handson-app)と完全に一致させる必要があります。一致しないとデプロイステージでコンテナが見つからず失敗します。このファイルにより ECS がどのイメージをデプロイするかを判断します。
buildspec.yml から参照するアカウント ID を SSM に保存します。
aws ssm put-parameter \ --name /handson/aws-account-id \ --value "$(aws sts get-caller-identity --query Account --output text)" \ --type String \ --region ap-northeast-1GitHub リポジトリに app.js・Dockerfile・buildspec.yml の 3 ファイルが存在すれば準備完了です。
CodeBuild がビルドした Docker イメージを保管する ECR リポジトリを作成します。
AWS マネジメントコンソールで 「Elastic Container Registry」 を検索して開きます。「リポジトリを作成」 をクリックします。
「リポジトリを作成」をクリックします。
古いイメージが蓄積しないよう、最新 10 件のみ保持するポリシーを設定します。
リポジトリを開き 「ライフサイクルポリシー」→「ルールを作成」 をクリックします。
ECR リポジトリ一覧に handson-app が表示されれば成功です。URI(<account-id>.dkr.ecr.ap-northeast-1.amazonaws.com/handson-app)をメモしておきます。
CodePipeline が GitHub リポジトリを監視できるよう、AWS と GitHub を接続します。
AWS マネジメントコンソールで 「CodePipeline」 を検索して開きます。左メニューの 「設定」→「接続」→「接続を作成」 をクリックします。
「GitHub に接続」をクリックします。
GitHub の認証ページにリダイレクトされます。「AWS Connector for GitHub」 アプリのインストールを許可します。
handson-app)を選択して「Install」接続一覧でステータスが 「利用可能」 になれば成功です。「保留中」のままの場合は「保留中の接続を更新」をクリックしてください。
Docker ビルドと ECR プッシュを行う CodeBuild プロジェクトを作成します。
「CodeBuild」 を検索して開きます。「ビルドプロジェクトを作成する」 をクリックします。
| 設定項目 | 設定値 |
|---|---|
| 環境イメージ | マネージド型イメージ |
| コンピューティング | EC2 |
| オペレーティングシステム | Amazon Linux |
| ランタイム | Standard |
| イメージ | aws/codebuild/standard:7.0(最新) |
| 特権モード | ✅ 有効(Docker ビルドに必須) |
| サービスロール | 新しいサービスロール → codebuild-handson-role |
Docker デーモンを使用するため「特権モードを有効にする」にチェックを入れてください。これなしでは docker build が失敗します。
プロジェクト作成後、自動作成された IAM ロール codebuild-handson-role に以下のポリシーを追加します。
IAM コンソール → ロール → codebuild-handson-role → 「許可を追加」→「ポリシーをアタッチ」
AmazonEC2ContainerRegistryPowerUser — ECR への push 権限AmazonSSMReadOnlyAccess — SSM パラメーター読み取り権限CodeBuild コンソールで handson-build を選択 →「ビルドを開始」をクリックします。ビルドログを確認し「成功」になれば ECR にイメージが push されています。
Source・Build・Deploy の 3 ステージで構成されるパイプラインを作成します。
CodePipeline コンソールで 「パイプラインを作成する」 をクリックします。
「次へ」をクリックします。
「次へ」をクリックします。
「次へ」をクリックします。
「次へ」→「パイプラインを作成する」をクリックします。
「Amazon ECS」プロバイダーはローリングアップデートです。ダウンタイムゼロの Blue/Green デプロイが必要な場合は「CodeDeploy」プロバイダーを選択し、appspec.yml の設定が別途必要になります。
パイプライン作成後、自動的に最初の実行が始まります。Source → Build → Deploy の各ステージが順に「成功」になれば構築完了です(初回は 5〜10 分かかります)。
コードを変更して git push し、パイプラインが自動起動してデプロイされることを確認します。
app.js の VERSION を変更します。
const VERSION = process.env.APP_VERSION || 'v2.0'; // v1.0 → v2.0 に変更git add app.js git commit -m "feat: update version to v2.0" git push origin main
CodePipeline コンソールで handson-pipeline を開きます。数秒〜数十秒でパイプラインが自動起動し、各ステージが順に実行されます。
| ステージ | 確認ポイント | 所要時間目安 |
|---|---|---|
| Source | GitHub から最新コミットを取得 | 〜30 秒 |
| Build | Docker ビルド・ECR プッシュ | 2〜5 分 |
| Deploy | ECS サービスの新タスク起動 | 1〜3 分 |
ECS コンソール → クラスター → handson-ecs-cluster → サービス → handson-ecs-service → タスクタブを確認します。新しいタスクが起動し旧タスクが停止すれば成功です。
ALB の DNS 名またはサービスのパブリック IP にアクセスして Version: v2.0 が表示されれば CI/CD パイプライン完成です。
今後は main ブランチへの push だけで自動的にビルド・デプロイが行われます。
ECS Fargate・CodeBuild・CodePipeline(パイプライン実行数)・ECR(イメージ保管)などで課金が発生します。
handson-pipeline →「削除」handson-build →「削除」handson-github-connection →「削除」handson-app →「削除」codepipeline-* バケット →「空にする」→「削除」codebuild-handson-role・AWSCodePipelineServiceRole-* を削除/handson/aws-account-id →「削除」| 習得したスキル | 実践内容 |
|---|---|
| CI/CD パイプライン設計 | Source → Build → Deploy の 3 ステージ構成 |
| buildspec.yml | Docker ビルド・ECR プッシュ・imagedefinitions.json 生成 |
| GitHub 連携 | CodeStar Connections による OAuth 接続 |
| ECS 自動デプロイ | imagedefinitions.json を使ったローリングアップデート |
| ECR ライフサイクル | 古いイメージの自動削除ポリシー |