AWS CodePipelineでS3バケットへSPAアプリケーションをデプロイ!

AWS CodePipelineでS3バケットへSPAアプリケーションをデプロイ!

こんにちは!

今回は、CodePipeline を用いて SPA アプリケーションをデプロイする方法について説明したいと思います!設定方法のコツなどもお伝えしますので、ぜひ参考にしてみてください。

想定する読者

  • CodePipeline について知りたいヒト
  • SPA アプリケーションの CI/CD について知りたいヒト
  • CI/CD 構築に AWS を活用したいヒト

はじめに

前提の知識として、CI 部分は CodeBuild を利用し、CD 部分は CodePipeline を利用して S3 バケットにデプロイを行いますので、この点をご理解の上、以降の記事をお読みください!

また本記事では BitBucket を利用した CI/CD を構築するため、それに合わせた CloudFormation テンプレートをご紹介していきます。

今回 CI/CD で利用する AWS サービスは以下になります。

  • CodeBuild
  • CodePipeline
  • CodeStar(BitBucket を利用するため必要)
  • S3
  • IAM
  • CloudFormation

それでは早速説明していきましょう。

S3 バケットの作成

SPA アプリケーションの CI/CD を構築するため、S3 バケットを作成する必要があります。

手動で作成する場合は、SPA をデプロイするための S3 バケットのみを作成すればよいのですが、CloudFormation を利用する場合は、CodePipeline のアーティファクト用の S3 バケットが必要になりますので、この点を注意してテンプレートを作成しましょう。

CloudFormation では以下のようなテンプレートで S3 バケットを構築します。

Resources:
  ExampleBucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: sample-app
      WebsiteConfiguration:
        IndexDocument: index.html
        ErrorDocument: index.html

  CodepipelineBucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: sample-codepipeline-artifact

CodePipeline の設定

次に CodePipeline を作成していきます。CodePipeline は CI/CD のプロセスおよびステージを設定することで、環境に合わせた CI/CD パイプラインを構築することが可能です。

SPAアプリケーションの場合は、以下のステージが必要になります。

  • ソースステージ
  • ビルドステージ
  • デプロイステージ

これらを踏まえパイプラインを構築していきます。

CloudFormation を利用する場合

CloudFormation では以下のようになります。

Resources:
  CodePipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      Name: sample-codepipeline
      RoleArn: !GetAtt CodepipelineServiceRole.Arn
      ArtifactStore: 
        Location: !Ref CodepipelineBucket
        Type: S3
      Stages: 
      - Name: Source
        Actions: 
        - Name: Source
          ActionTypeId: 
            Category: Source
            Owner: AWS
            Provider: CodeStarSourceConnection
            Version: '1'
          Configuration: 
            # ブランチを指定
            BranchName: master
            # BitBucketを連携
            ConnectionArn: !Ref CodeStar
            # リポジトリを指定
            FullRepositoryId: sample-repository
            OutputArtifactFormat: CODE_ZIP
          OutputArtifacts: 
          - Name: SourceArtifact
          Namespace: SourceVariables
          RunOrder: 1
      - Name: Build
        Actions: 
        - Name: Build
          ActionTypeId: 
            Category: Build
            Owner: AWS
            Provider: CodeBuild
            Version: '1'
          Configuration: 
            EnvironmentVariables: !Sub |
              [
                {"name":"STAGE","value":"dev","type":"PLAINTEXT"}
              ]
            ProjectName: !Ref CodeBuild
          InputArtifacts: 
          - Name: SourceArtifact
          OutputArtifacts: 
          - Name: BuildArtifact
          Namespace: BuildVariables
          RunOrder: 1
      - Name: Deploy
        Actions:
        - Name: Deploy
          ActionTypeId:
            Category: Deploy
            Owner: AWS
            Provider: S3
            Version: '1'
          Configuration:
            BucketName: !Ref ExampleBucket
            Extract: true
          InputArtifacts:
          - Name: BuildArtifact
          Namespace: DeployVariables
          RunOrder: 1

上記を解説していくと、Stage のパラメータから Source, Build, Deploy の3つのステージを設定しております。

Source 部分では CI/CD をトリガーするリポジトリを指定し、Build 部分では 作成する CodeBuild を参照しております。Build ステージの環境変数に関しては CodePipeline のテンプレートにて設定します。最後に Deploy 部分ではデプロイ先の S3 バケットを指定することで CD 部分の設定を行なっております。

なお、BitBucket を利用するには CodeStar のテンプレートが必要となりますので、以下の記述も行ってください。手動で行う場合は該当しません。

Resources:
  CodeStar:
    Type: 'AWS::CodeStarConnections::Connection'
    Properties:
      ConnectionName: MyConnection
      ProviderType: Bitbucket

手動の場合

手動の場合は、以下のようにマネジメントコンソールの案内に従えば簡単に構築できます。

パイプライン名を入力しましょう、サービスロールも併せて作成されます。

「 Bitbucket に接続」をクリックすると、BitBucket にログインします。そのあとに CodePipeline の作成ウィザードに戻るのでリポジトリとブランチを選択して次の画面に移動しましょう。

CodeBuild は「プロジェクトを作成する」をクリックすれば作成できます。手動の場合だと、作成ウィザードに従えば簡単に構築できます。

最後にデプロイ先の S3 バケットを指定すればパイプラインの完成です。

手動で CodePipeline を作成される方は、作成ウィザードに従えば、その過程で CodeBuild を作成できます。事前に作成される場合は、次のセクションを参考にしてください。

CodeBuild の設定

CodeBuild はビルドを実行する AWS サービスです。そのため CodePipeline のビルドフェーズで利用します。こちらも CloudFormation と手動に分けて解説します。

CodeBuild に必要な設定は以下になります。

  • ソース
  • ビルドの環境設定

またログ設定も行えますので、ここはお好みで設定してください。

CloudFormation の場合

CloudFormation で作成する場合は、以下のようにテンプレートの記述を行ってください。

Resources:
  CodeBuild:
    Type: AWS::CodeBuild::Project
    Properties:
      Name: sample-build
      Source: 
        BuildSpec: buildspec.yml
        Type: CODEPIPELINE
      Artifacts: 
        Name: sample-codepipeline
        Packaging: NONE
        Type: CODEPIPELINE
      Cache: 
        Type: NO_CACHE
      # 環境設定
      Environment: 
        ComputeType: BUILD_GENERAL1_LARGE
        Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0
        ImagePullCredentialsType: CODEBUILD
        PrivilegedMode: false
        Type: LINUX_CONTAINER
      ServiceRole: !GetAtt CodebuildServiceRole.Arn
      TimeoutInMinutes: 60
      QueuedTimeoutInMinutes: 480
      BadgeEnabled: false
      # ログ設定
      LogsConfig: 
        CloudWatchLogs: 
          Status: ENABLED
        S3Logs: 
          Status: DISABLED
          EncryptionDisabled: false

上記の各パラメータを、目的に合わせて変更してください。

手動の場合

手動で作成される方は、作成ウィザードに従って作成すれば問題ありません。マネジメントコンソールでは、ビルドプロジェクトの名前、ソースの設定、ビルドを実行する環境設定を行えば作成が可能となります。

環境設定は、こだわりがなければ Amazon Linux を選択しましょう。上記の画像が例になります。

手動の場合は、事前に作成するより CodePipeline の作成ウィザードの過程で作成したほうが設定ミスが少なくなるため、そちらの方をおすすめいたします。

BuildSpec ファイルについて

CodeBuild では、BuildSpec ファイル(デフォルトで buildspec.yml という名前になります、ファイル名は変更可能です)というビルドの仕様を記述したファイルをリポジトリのルートディレクトリに設置することで、仕様通りにビルドを実行します。

BuildSpec ファイルは以下のように記述します。

 version: 0.2
 phases:
   install:
     runtime-versions:
       nodejs: 12
     commands:
       - yarn
       - yarn build:${STAGE}
 artifacts:
   files:
     - '**/*'
   base-directory: dist

上記のように CodePipeline のビルドステージにて環境変数を設定すれば、環境に応じてデプロイが可能となります。コマンド部分は、目的に合わせて設定してください。

CloudFormation で作成する場合の注意点

CloudFormation で作成された方は上記で紹介したテンプレートに加え、CodePipeline と CodeBuild に必要な IAM ロールを準備する必要があるため、以下を必ず追記してください。

Resources:
  CodebuildServiceRole:
    Type: AWS::IAM::Role
    Properties:
      Path: /service-role/
      RoleName: sample-codebuild-DefaultServiceRole
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement: 
          - Effect: Allow
            Principal: 
              Service: 
                - codebuild.amazonaws.com
            Action: 
              - sts:AssumeRole
      MaxSessionDuration: 3600
      ManagedPolicyArns: 
      - arn:aws:iam::aws:policy/AdministratorAccess

  CodepipelineServiceRole:
    Type: AWS::IAM::Role
    Properties:
      Path: /service-role/
      RoleName: sample-codepipeline-DefaultServiceRole
      AssumeRolePolicyDocument: 
        Version: '2012-10-17'
        Statement: 
          - Effect: Allow
            Principal: 
              Service: 
                - codepipeline.amazonaws.com
            Action: 
              - sts:AssumeRole
      MaxSessionDuration: 3600
      ManagedPolicyArns: 
      - arn:aws:iam::aws:policy/AdministratorAccess

また、CloudFormation で CodePipeline を作成した場合、初回の実行は必ず失敗します。これは、参照しているリポジトリとの接続ができていないからです。

これを回避するには、事前に BitBucket に接続してテンプレートの参照先を作成した接続名で指定するしかありません。

ただ初回の実行が失敗するだけで、デプロイ後にマネジメントコンソールで設定すれば実行することができます。どちらでも問題なく CodePipeline を実行することができますのでご安心ください。

以下では、パイプライン実行が失敗したときの接続の設定方法をご紹介します。

上記のように失敗します

この画面で左ペインの「設定>接続」をクリックします。

作成した CodeStar が表示されているので、接続名を選択したあと、「保留中の接続を更新」をクリックすれば接続が完了します。

このあとにパイプラインを実行すると無事デプロイすることができます。

パイプラインの実行

これまでの作業が完了したら、あとは作成したパイプラインを実行するだけです。パイプライン実行後、マネジメントコンソール上で作成した CodePipeline を確認してみましょう。

パイプラインおよびデプロイが完了されていますね!

これにより S3 バケットにファイルが配置されました。あとはご自身の SPA アプリケーションの挙動を確認してみてください!無事に動いているはずです。

関連記事

まとめ

CodePipeline を利用することで、CI/CD 部分の構築がかなり楽になります。また CloudFormation を利用することで、とりあえず簡易的な CI/CD を構築したいときに素早くパイプラインを作成できますので非常に役に立ちます。ぜひご活用ください!

このブログでは、AWS の記事をどんどん公開しておりますので、ご興味のある方はほかの記事もご覧いただければと思います。

AWS に関する開発は、お気軽にお問い合わせください。