ぴよまるの雑多な技術所

間違えて休職中ってずっと書いていて心配されていました。全部ちょっとずつ齧って好きって思える技術を見つけたい。研究分野は数理最適化。

Serverless Frameworkを使ってLambda + API GatewayのプロジェクトをProduction / Developmentに分けて開発する

概要

Lambda + API GatewayでSPAからAPI Gateway経由でAPIを叩くという構成の時のServerless Frameworkの設定についてまとめます。 長くなりそうなので今回はフロントエンド側のServerless Frameworkの設定内容と、最初のデプロイについてに絞りました。

構成

Lambda, API Gateway, S3, CloudFront

Serverless Frameworkの設定(フロントエンド)

S3、CloudFrontを自動で作成するという内容でyamlを書きます。 S3のバケットポリシー、CloudFrontのhttpsの設定もしています。

serverless.yml

service: test-serverless #ここは自由に名前を入力する

provider:
  name: aws 
  region: ap-northeast-1
  stage: ${opt:stage, self:custom.defaultStage}
  # profile: (もしProfileでアカウントをわけていればここに入力)

custom:
  defaultStage: development
  env:
    development:
      siteName: ${self:provider.stage}.${self:service}

resources:
  Resources:
    StaticContentsS3:
      Type: AWS::S3::Bucket
      DeletionPolicy: Retain
      Properties:
        BucketName: ${self:custom.env.${self:provider.stage}.siteName}
        AccessControl: Private
        WebsiteConfiguration:
          IndexDocument: index.html
          ErrorDocument: index.html
        Tags:
          - Key: Environment
            Value: ${self:provider.stage}

    StaticContentsS3Policy:
      Type: AWS::S3::BucketPolicy
      Properties:
        Bucket:
          Ref: StaticContentsS3
        PolicyDocument:
          Statement:
            - Effect: Allow
              Principal:
                CanonicalUser:
                  Fn::GetAtt:
                    - StaticCloudFrontOriginAccessIdentity
                    - S3CanonicalUserId
              Action: s3:GetObject
              Resource:
                Fn::Join:
                  - "/"
                  - - Fn::GetAtt:
                        - StaticContentsS3
                        - Arn
                    - "*"

    StaticContentsCloudFront: #CloudFrontの設定
      Type: AWS::CloudFront::Distribution
      Properties:
        DistributionConfig:
          Enabled: true
          Comment: "Delivery static contents"
          PriceClass: PriceClass_200 # CloudFrontを配置する場所
          DefaultRootObject: index.html
          CustomErrorResponses:
            - ErrorCode: 403
              ResponseCode: 200
              ResponsePagePath: /index.html
            - ErrorCode: 404
              ResponseCode: 200
              ResponsePagePath: /index.html
          Origins:
            - Id: S3Origin
              DomainName:
                Fn::GetAtt:
                  - StaticContentsS3
                  - DomainName
              S3OriginConfig:
                OriginAccessIdentity:
                  Fn::Join:
                    - "/"
                    - - origin-access-identity
                      - cloudfront
                      - Ref: StaticCloudFrontOriginAccessIdentity
          DefaultCacheBehavior:
            AllowedMethods:
              - HEAD
              - GET
            CachedMethods:
              - HEAD
              - GET
            Compress: true
            DefaultTTL: 900
            MaxTTL: 1200
            MinTTL: 600
            ForwardedValues:
              QueryString: true
              Cookies:
                Forward: none
            SmoothStreaming: false
            TargetOriginId: S3Origin
            ViewerProtocolPolicy: redirect-to-https
          ViewerCertificate:
            CloudFrontDefaultCertificate: 'true'

    StaticCloudFrontOriginAccessIdentity:
      Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
      Properties:
        CloudFrontOriginAccessIdentityConfig:
          Comment:
            Ref: AWS::StackName

  Outputs:
    StaticContentsCloudFrontUrl:
      Value:
        Fn::Join:
          - ""
          - - "https://"
            - Fn::GetAtt:
              - StaticContentsCloudFront
              - DomainName

デプロイ手順

まずはServerless Frameworkのデプロイコマンドを叩きます。こうするとCloudFormation経由でAWSリソースが作られます。

serverless deploy --stage development

次に出来上がったバケットに対して、フロントエンドのソースコードをアップロードします。詳細は割愛しますが、例えばNuxt.jsを使っている場合は「yarn generate」でできあがったdistの中のファイルをそのままアップロードすれば大丈夫です。

ここまでできるとCloudFrontのURLをブラウザから叩けばフロントエンドの動きが確認できます。

serverless deploy --stage production

という風にすれば、別の名前のS3バケットとCloudFrontができます。何か試すときはdevelopmentで試して、動作確認ができたらproductionにあげる…ということが簡単にできます。(普通はその間にstagingがありますが、今回は突然productionにしています。)

後編は後で書きます!