AWS CodePipelineでCI/CD構築|コード変更から本番デプロイまでの自動化

kento_morota 17分で読めます

「コードの変更を本番環境に反映するのに毎回手作業が必要で、ミスが怖い」「テスト実行を忘れて不具合がリリースされた」――開発・運用現場でこうした問題を抱えていませんか。

この記事では、AWS CodePipelineを中心としたCI/CD(継続的インテグレーション/継続的デリバリー)パイプラインの構築方法を解説します。コードのプッシュからビルド、テスト、本番デプロイまでを自動化し、リリースの品質と速度を向上させる実践的な手順を紹介します。

CI/CDとは?自動化がもたらす開発効率の向上

CI/CDは、ソフトウェア開発におけるビルド・テスト・デプロイの自動化プロセスです。

CI(Continuous Integration:継続的インテグレーション)は、開発者がコードをリポジトリにプッシュするたびに、自動でビルドとテストを実行する仕組みです。コードの問題を早期に発見し、統合の手間を減らします。

CD(Continuous Delivery/Deployment:継続的デリバリー/デプロイメント)は、CIで検証されたコードを、ステージング環境や本番環境へ自動でデプロイする仕組みです。

手動デプロイとCI/CDの比較

項目 手動デプロイ CI/CD自動化
デプロイ時間 30分〜数時間 5〜15分
ヒューマンエラー 手順漏れ・設定ミスが発生 自動化により排除
テスト実行 忘れることがある 毎回必ず実行
リリース頻度 週1回〜月1回 1日複数回も可能
ロールバック 手動で戻す必要 自動ロールバック可能
監査証跡 記録が残りにくい 全履歴を自動記録

AWS CI/CDサービスの全体像

AWSは、CI/CDパイプラインを構成するための複数のマネージドサービスを提供しています。

サービス 役割 対応する工程
CodeCommit Gitリポジトリ ソースコード管理
CodeBuild ビルド・テスト環境 ビルド、ユニットテスト
CodeDeploy デプロイ自動化 EC2/ECS/Lambdaへのデプロイ
CodePipeline パイプラインのオーケストレーション 各工程の連携・順序制御

CodePipelineが全体のオーケストレーターとして機能し、ソース取得、ビルド、デプロイの各ステージを連携させます。ソースリポジトリにはCodeCommitの代わりにGitHubやBitBucketを使うこともできます。

パイプラインの基本フロー

コードプッシュ
    │
    ▼
┌─Source Stage──────────┐
│  CodeCommit / GitHub   │
│  コード取得             │
└────────────────────────┘
    │
    ▼
┌─Build Stage───────────┐
│  CodeBuild             │
│  ビルド・テスト実行      │
└────────────────────────┘
    │
    ▼
┌─Deploy Stage(Staging)─┐
│  CodeDeploy            │
│  ステージング環境デプロイ │
└────────────────────────┘
    │
    ▼
┌─Approval Stage────────┐
│  手動承認               │
│  動作確認後に承認        │
└────────────────────────┘
    │
    ▼
┌─Deploy Stage(Prod)────┐
│  CodeDeploy            │
│  本番環境デプロイ        │
└────────────────────────┘

CodeBuildでビルド・テストを自動化する

CodeBuildは、ソースコードのコンパイル、テスト実行、デプロイ用アーティファクトの作成を行うフルマネージドのビルドサービスです。ビルド環境のサーバー管理は不要で、使った分だけの課金です。

buildspec.ymlの作成

CodeBuildの動作は、リポジトリのルートに配置するbuildspec.ymlで定義します。

Node.jsアプリケーションの場合:

version: 0.2

phases:
  install:
    runtime-versions:
      nodejs: 20
    commands:
      - npm ci

  pre_build:
    commands:
      - echo "Running lint..."
      - npm run lint
      - echo "Running unit tests..."
      - npm test

  build:
    commands:
      - echo "Building application..."
      - npm run build

  post_build:
    commands:
      - echo "Build completed on $(date)"

artifacts:
  files:
    - '**/*'
  base-directory: dist

reports:
  test-reports:
    files:
      - 'test-results/junit.xml'
    file-format: JUNITXML

cache:
  paths:
    - 'node_modules/**/*'

各フェーズの役割は以下の通りです。

  • install:ランタイムの指定と依存パッケージのインストール
  • pre_build:リント・テストの実行(ここで失敗するとビルドは中断)
  • build:アプリケーションのビルド
  • post_build:ビルド後の処理(通知やクリーンアップ)

Dockerイメージのビルドとプッシュ

ECS/Fargateにデプロイする場合、CodeBuildでDockerイメージをビルドしてECR(Elastic Container Registry)にプッシュします。

version: 0.2

env:
  variables:
    AWS_ACCOUNT_ID: "123456789012"
    IMAGE_REPO_NAME: "my-app"
    IMAGE_TAG: "latest"

phases:
  pre_build:
    commands:
      - echo "Logging in to Amazon ECR..."
      - aws ecr get-login-password --region ap-northeast-1 |
        docker login --username AWS --password-stdin
        ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com
      - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
      - IMAGE_TAG=${COMMIT_HASH:-latest}

  build:
    commands:
      - echo "Building Docker image..."
      - docker build -t ${IMAGE_REPO_NAME}:${IMAGE_TAG} .
      - docker tag ${IMAGE_REPO_NAME}:${IMAGE_TAG}
        ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/${IMAGE_REPO_NAME}:${IMAGE_TAG}

  post_build:
    commands:
      - echo "Pushing Docker image to ECR..."
      - docker push
        ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/${IMAGE_REPO_NAME}:${IMAGE_TAG}
      - printf '[{"name":"my-app","imageUri":"%s"}]'
        ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/${IMAGE_REPO_NAME}:${IMAGE_TAG}
        > imagedefinitions.json

artifacts:
  files:
    - imagedefinitions.json

出力されるimagedefinitions.jsonをCodePipelineのデプロイステージに渡すことで、ECSのタスク定義を自動更新できます。

CodeDeployでデプロイを安全に自動化する

CodeDeployは、EC2インスタンスやECSサービス、Lambda関数へのデプロイを自動化するサービスです。特にゼロダウンタイムでのデプロイ戦略が充実しています。

デプロイ戦略の選択

戦略 概要 適用先 リスク
AllAtOnce 全インスタンスに一括デプロイ 開発環境 高(ダウンタイムあり)
Rolling 一定数ずつ順次デプロイ EC2
Blue/Green 新環境を別に作成して切り替え EC2/ECS
Canary 一部トラフィックから段階的に移行 ECS/Lambda 最低

本番環境ではBlue/GreenまたはCanaryデプロイを推奨します。問題が発生した場合に即座にロールバックできるためです。

ECSへのBlue/Greenデプロイ設定

ECSサービスへのBlue/Greenデプロイでは、2つのターゲットグループを使い、新しいタスク定義でタスクを起動した後、ALBのリスナーを切り替えます。

CodeDeployのappspec.ymlの例です。

version: 0.0
Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: "arn:aws:ecs:ap-northeast-1:123456789012:task-definition/my-app:1"
        LoadBalancerInfo:
          ContainerName: "my-app"
          ContainerPort: 8080

Hooks:
  - BeforeInstall: "LambdaFunctionToValidateBeforeInstall"
  - AfterInstall: "LambdaFunctionToValidateAfterInstall"
  - AfterAllowTestTraffic: "LambdaFunctionToRunIntegrationTests"
  - BeforeAllowTraffic: "LambdaFunctionToValidateBeforeTraffic"
  - AfterAllowTraffic: "LambdaFunctionToRunSmokeTests"

Hooksでは、各デプロイステップの前後にLambda関数を実行してバリデーションを行えます。テストトラフィックを送って動作確認した後に、本番トラフィックを切り替える安全なフローを構築できます。

CodePipelineでパイプラインを統合する

各サービスの設定ができたら、CodePipelineで全体を統合します。

パイプライン作成の手順

AWS CLIでパイプラインを作成する場合、JSON形式でパイプライン定義を記述します。

{
  "pipeline": {
    "name": "my-app-pipeline",
    "roleArn": "arn:aws:iam::123456789012:role/CodePipelineServiceRole",
    "stages": [
      {
        "name": "Source",
        "actions": [
          {
            "name": "SourceAction",
            "actionTypeId": {
              "category": "Source",
              "owner": "AWS",
              "provider": "CodeCommit",
              "version": "1"
            },
            "configuration": {
              "RepositoryName": "my-app",
              "BranchName": "main"
            },
            "outputArtifacts": [{"name": "SourceOutput"}]
          }
        ]
      },
      {
        "name": "Build",
        "actions": [
          {
            "name": "BuildAction",
            "actionTypeId": {
              "category": "Build",
              "owner": "AWS",
              "provider": "CodeBuild",
              "version": "1"
            },
            "configuration": {
              "ProjectName": "my-app-build"
            },
            "inputArtifacts": [{"name": "SourceOutput"}],
            "outputArtifacts": [{"name": "BuildOutput"}]
          }
        ]
      },
      {
        "name": "DeployStaging",
        "actions": [
          {
            "name": "DeployStagingAction",
            "actionTypeId": {
              "category": "Deploy",
              "owner": "AWS",
              "provider": "CodeDeploy",
              "version": "1"
            },
            "configuration": {
              "ApplicationName": "my-app",
              "DeploymentGroupName": "staging"
            },
            "inputArtifacts": [{"name": "BuildOutput"}]
          }
        ]
      },
      {
        "name": "Approval",
        "actions": [
          {
            "name": "ManualApproval",
            "actionTypeId": {
              "category": "Approval",
              "owner": "AWS",
              "provider": "Manual",
              "version": "1"
            },
            "configuration": {
              "NotificationArn": "arn:aws:sns:ap-northeast-1:123456789012:approval-notifications"
            }
          }
        ]
      },
      {
        "name": "DeployProduction",
        "actions": [
          {
            "name": "DeployProductionAction",
            "actionTypeId": {
              "category": "Deploy",
              "owner": "AWS",
              "provider": "CodeDeploy",
              "version": "1"
            },
            "configuration": {
              "ApplicationName": "my-app",
              "DeploymentGroupName": "production"
            },
            "inputArtifacts": [{"name": "BuildOutput"}]
          }
        ]
      }
    ]
  }
}

ステージング環境へのデプロイ後に手動承認ステージを入れることで、動作確認を行ってから本番にリリースできます。完全自動化が目標ですが、最初はこのように承認ステップを入れておくと安心です。

GitHubとの連携

ソースリポジトリにGitHubを使う場合、CodePipelineのソースステージでGitHub(バージョン2)接続を設定します。AWS CodeStar Connectionsを通じてGitHubと連携し、プルリクエストのマージやブランチへのプッシュをトリガーにパイプラインを起動できます。

CI/CDパイプラインのセキュリティと権限管理

CI/CDパイプラインは本番環境へのデプロイ権限を持つため、セキュリティの確保が極めて重要です。

IAMロールの最小権限設計

各サービスのIAMロールには、必要最小限の権限のみを付与します。IAMのベストプラクティスに従い、以下のようにロールを分離してください。

  • CodePipeline実行ロール:パイプラインの各ステージを呼び出す権限のみ
  • CodeBuildサービスロール:ビルドに必要なリソース(ECR、S3など)へのアクセス権限
  • CodeDeployサービスロール:デプロイ先(ECS、EC2、Lambda)の操作権限

シークレット管理

ビルドやデプロイで使う機密情報(APIキー、データベースパスワードなど)は、buildspec.ymlにハードコードしてはいけません。以下の方法で安全に管理します。

  • AWS Systems Manager Parameter Store:暗号化されたパラメータとして保存
  • AWS Secrets Manager:自動ローテーション機能付きのシークレット管理
# buildspec.ymlでのParameter Store参照例
env:
  parameter-store:
    DB_PASSWORD: /production/database/password
    API_KEY: /production/external-api/key

パイプラインの監視とトラブルシューティング

CI/CDパイプラインも他のシステムと同様に、監視体制の構築が必要です。

パイプライン失敗時の通知設定

CodePipelineの状態変化をCloudWatch Eventsでキャプチャし、SNS経由で通知を送ります。

# パイプライン失敗時のCloudWatch Eventsルール
{
  "source": ["aws.codepipeline"],
  "detail-type": ["CodePipeline Pipeline Execution State Change"],
  "detail": {
    "state": ["FAILED"]
  }
}

CloudWatchの監視設定ガイドで通知の詳細設定方法も確認してください。

よくあるトラブルと対処法

  • ビルド失敗:CodeBuildのログを確認し、依存関係の問題やテスト失敗の原因を特定する
  • 権限エラー:IAMロールのポリシーを確認し、不足している権限を追加する
  • デプロイタイムアウト:ヘルスチェックの設定を見直し、アプリケーションの起動時間に合った値に調整する
  • アーティファクトの受け渡しエラー:ステージ間のアーティファクト名が一致しているか確認する

まとめ:小さく始めて段階的に自動化を進めよう

AWS CodePipelineを使ったCI/CDパイプラインの構築方法を解説しました。

  • CodeBuildでビルドとテストを自動化し、品質を担保する
  • CodeDeployでBlue/Greenデプロイにより安全にリリースする
  • CodePipelineで全体を統合し、コードプッシュから本番反映までを自動化する
  • 手動承認ステージを入れて、段階的に自動化レベルを上げていく
  • IAMの最小権限とシークレット管理でセキュリティを確保する

最初は手動承認ありのシンプルなパイプラインから始め、自動テストの充実に合わせて承認ステップを減らしていくのが現実的なアプローチです。インフラのコード管理についてはTerraformによるインフラ管理も合わせて導入を検討してください。

#AWS#CodePipeline#CI/CD
共有:
無料メルマガ

週1回、最新の技術記事をお届け

AI・クラウド・開発の最新記事を毎週月曜にメールでお届けします。登録は無料、いつでも解除できます。

プライバシーポリシーに基づき管理します

AI活用のヒントをお探しですか?お気軽にご相談ください。

まずは話だけ聞いてもらう