Serverless FrameworkでS3にデプロイしたWEBアプリに独自ドメインを設定

前回の記事

Serverless Frameworkを使ってAWS S3にAngularアプリを自動デプロイする


今回やりたいこと

  • 前回と同じくServerless Frameworkを使ってAWS S3にAngularアプリをデプロイする。
  • デプロイしたAngularアプリに独自ドメインを使用してアクセスできるようにする。

 

前提

  • 前回の記事の内容を把握済み。
  • AWS ACMで証明書を発行済み。
  • AWS Route53で独自ドメインを取得済み。


システム構成

Serverless + Angular + S3 + ACMでのシステム構成











serverless.ymlを修正

前回の記事で作成したserverless.ymlを修正します。

service: angular-test-app

frameworkVersion: '2'

plugins:
  - serverless-single-page-app-plugin
  - serverless-cloudfront-invalidate

provider:
  name: aws
  stage: ${env:STAGE}
  region: ap-northeast-1
  stackName: ${self:service}-${self:provider.stage}
  environment:
    stage: ${self:provider.stage}

custom:
  # ↓ここを追加↓
  domainName: Route53で取得した独自ドメイン
  hostedZoneId: Route53で取得した独自ドメインのホストゾーンID
  acmCertificateArn: ACMで発行した証明書のARN
  # ↑ここを追加↑
  s3Bucket: ${self:service}-deploy-${self:provider.stage}
  s3LocalPath: dist/
  cloudfrontInvalidate:
    - distributionIdKey: CDNDistributionId
      autoInvalidate: true
      items:
        - '/*'

resources:
  Resources:
    WebAppS3Bucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: ${self:custom.s3Bucket}
        AccessControl: PublicRead
        WebsiteConfiguration:
          IndexDocument: index.html
          ErrorDocument: index.html

    WebAppS3BucketPolicy:
      Type: AWS::S3::BucketPolicy
      Properties:
        Bucket:
          Ref: WebAppS3Bucket
        PolicyDocument:
          Statement:
            - Sid: PublicReadGetObject
              Effect: Allow
              Principal: "*"
              Action:
                - s3:GetObject
              Resource:
                Fn::Join: ["", ["arn:aws:s3:::", { "Ref": "WebAppS3Bucket" }, "/*"]]

    WebAppCloudFrontDistribution:
      Type: AWS::CloudFront::Distribution
      Properties:
        DistributionConfig:
          Origins:
            - DomainName:
                Fn::Join: ["", [{ "Ref": "WebAppS3Bucket" }, ".s3-ap-northeast-1.amazonaws.com"]]
              Id: WebApp
              CustomOriginConfig:
                HTTPPort: 80
                HTTPSPort: 443
                OriginProtocolPolicy: https-only
          PriceClass: PriceClass_200
          Enabled: 'true'
          DefaultRootObject: index.html
          CustomErrorResponses:
            - ErrorCode: 404
              ResponseCode: 200
              ResponsePagePath: /index.html
            - ErrorCode: 403
              ResponseCode: 200
              ResponsePagePath: /index.html
          DefaultCacheBehavior:
            AllowedMethods:
              - DELETE
              - GET
              - HEAD
              - OPTIONS
              - PATCH
              - POST
              - PUT
            TargetOriginId: WebApp
            ForwardedValues:
              QueryString: 'false'
              Cookies:
                Forward: none
            ViewerProtocolPolicy: https-only
          # ↓ここを追加↓
          Aliases:
            - ${self:custom.domainName}
          ViewerCertificate:
            AcmCertificateArn: ${self:custom.acmCertificateArn}
            SslSupportMethod: sni-only
          # ↑ここを追加↑

    # ↓ここを追加↓
    WebSiteRecordSet:
      Type: AWS::Route53::RecordSet
      Properties:
        Name: ${self:custom.domainName}
        HostedZoneId: ${self:custom.hostedZoneId}
        Type: A
        AliasTarget:
          HostedZoneId: Z2FDTNDATAQYW2 # このIDはCloudFrontにエイリアスリソースレコードセットを作成する時に必要なAWS固有のIDです。
          DNSName:
            Fn::GetAtt: [ WebAppCloudFrontDistribution, DomainName ]
    # ↑ここを追加↑

  Outputs:
    WebAppS3BucketOutput:
      Value:
        'Ref': WebAppS3Bucket
    CDNDistributionId:
      Description: CDN distribution id.
      Value:
        Ref: WebAppCloudFrontDistribution



ビルド&デプロイ

# 環境変数の設定
## 任意のステージ名
$ export STAGE=dev
## デプロイ権限を持ったIAMユーザのアクセスキー&シークレットアクセスキー
$ export AWS_ACCESS_KEY_ID=XXX
$ export AWS_SECRET_ACCESS_KEY=XXX

# ビルド
$ npx ng build --prod

# デプロイ
$ npx sls deploy -v -s $STAGE
$ npx sls syncToS3 -v -s $STAGE

デプロイしたページを確認

ブラウザで https://独自ドメイン名 を開くとデプロイしたページを確認できます。