LoginSignup
2
1

More than 1 year has passed since last update.

【Rails+React】アプリをサーバレスデプロイしたい

Last updated at Posted at 2023-05-12

はじめに

これまでに投稿した記事の続きです。フロントエンドとバックエンドを別にしてデプロイしてきましたが、最終的にまとめてデプロイしました。詰まったことも併せて簡単にまとめてみます。

詰まったポイント

①フロントとAPI Gatewayの疎通

PostmanからAPI Gatewayにパラメータを送信してデータ操作ができることは確認済みなので、あとはフロントとAPI Gatewayの疎通を確認します。

そのためにまずはフロントでaxiosのアクセス先がAPI Gatewayのエンドポイントになっていることを確認します。


  const getTodos = async () => {
    try {
      const res = await axios.get('https://hogehoge/dev/todos');
      const backendResponse: Response = res.data;
      if (backendResponse.status === 200) {
        setTodos(backendResponse.todos);
      } else {
        console.error('Failed to get todos:', backendResponse);
      }
    } catch (error) {
      console.error('Failed to get todos:', error);
    }
  };

②バックエンドのcors設定

lambda.rb
        headers.merge!({
          'Access-Control-Allow-Origin': 'https://hogehoge.cloudfront.net',
          'Access-Control-Allow-Credentials': true,
          'Access-Control-Expose-Headers': 'Content-Disposition,X-Suggested-Filename',
          'Content-Security-Policy': "default-src 'self'"
        })

③serverless.ymlのcors設定

functions:
  app:
    events:
      - http:
          path: /
          method: ANY
          cors: &cors
            origin: https://hogehoge.cloudfront.net

④デプロイ前にフロントはビルドする

これを忘れていてしばらく時間を費やしました。axios箇所にエンドポイントを指定してもFailed to load resource: net::ERR_CONNECTION_REFUSEDというエラーが発生します。これはビルドしていないために変更点が反映されずlocalhostにアクセスしているということが原因でした…。 

動作確認

画面にアクセスしたとき

image.png

適当にToDoをつくります

image.png

画面でデータ操作できることが確認できました!
DynamoDBにも操作が反映されています。

image.png

最終的なserverless.yml

service: qiita-test

frameworkVersion: '3'

provider:
  name: aws
  runtime: ruby2.7
  timeout: 300

  region: ap-northeast-1
  deploymentBucket:
    name: qiita-test-bucket
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:*
      Resource:
        - arn:aws:dynamodb:ap-northeast-1:${aws:accountId}:table/*
    - Effect: 'Allow'
      Action:
        - s3:GetObject
        - s3:PutObject
        - s3:ListBucket
        - s3:DeleteObject
        - s3:GetObjectTagging
        - s3:PutBucketPolicy
      Resource:
        - arn:aws:s3:::${Bucket}
        - arn:aws:s3:::${Bucket}/*

  ecr:
    scanOnPush: true
    images:
      lambda_docker:
        path: ./backend

custom:
  deploymentBucket:
    blockPublicAccess: true
  s3Sync:
    - bucketName: ${self:service}-dev
      localDir: reactapp/build

functions:
  app:
    timeout: 30
    image:
      name: lambda_docker
    events:
      - http:
          path: /
          method: ANY
          cors: &cors
            origin: https://hogehoge.cloudfront.net
            headers:
              - Content-Type
              - X-Amz-Date
              - Authorization
              - X-Api-Key
              - X-Amz-Security-Token
              - X-Amz-User-Agent
              - Access-Control-Allow-Headers
              - Access-Control-Allow-Origin
              - Time-Zone
              - Cache-Control
            allowCredentials: false

      - http:
          path: /{proxy+}
          method: ANY
          cors: *cors

resources:
  Resources:
    Bucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: ${self:service}-dev
        WebsiteConfiguration:
          IndexDocument: index.html
        PublicAccessBlockConfiguration:
          BlockPublicAcls: true
          BlockPublicPolicy: true
          IgnorePublicAcls: true
          RestrictPublicBuckets: true
        CorsConfiguration:
          CorsRules:
            - AllowedMethods:
                - GET
                - HEAD
              AllowedOrigins:
                - '*'
    BucketPolicy:
      Type: AWS::S3::BucketPolicy
      Properties:
        Bucket: !Ref Bucket
        PolicyDocument:
          Statement:
            - Action:
                - s3:GetObject
              Effect: Allow
              Resource: !Sub arn:aws:s3:::${Bucket}/*
              Principal:
                Service: cloudfront.amazonaws.com
              Condition:
                StringEquals:
                  AWS:SourceArn: !Sub arn:aws:cloudfront::${aws:accountId}:distribution/${Distribution}    
    Distribution:
      Type: AWS::CloudFront::Distribution
      Properties:
        DistributionConfig:
          DefaultCacheBehavior:
            TargetOriginId: ${self:service}-dev
            ForwardedValues:
              QueryString: false
            ViewerProtocolPolicy: https-only
          Enabled: true
          DefaultRootObject: index.html
          Origins:
            -  Id: ${self:service}-dev
               DomainName: !GetAtt Bucket.RegionalDomainName
               S3OriginConfig:
                OriginAccessIdentity: ''
               OriginAccessControlId: !GetAtt CloudFrontOriginAccessControl.Id

    CloudFrontOriginAccessControl:
      Type: AWS::CloudFront::OriginAccessControl
      Properties: 
        OriginAccessControlConfig:
          Description: Default Origin Access Control
          Name: !Ref AWS::StackName
          OriginAccessControlOriginType: s3
          SigningBehavior: always
          SigningProtocol: sigv4
  Outputs:
    URL:
      Value: !Sub "https://${Distribution.DomainName}"
    DistributionId:
      Value: !Ref Distribution

plugins:
  - serverless-deployment-bucket
  - serverless-s3-sync

おわりに

ようやく一区切りつきました。今回は予めタスクを作って時間を測り、再現性を高める試みをしていたのですが、デプロイ周りで色々詰まってしまいました。次はアプリの内容にこだわってみたいです。まだまだ学ぶことが多いので頑張ります。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1