👏

ReactをCloudFront+S3でCICDする

2022/08/15に公開

はじめに

いままでサーバーサイドでレンダリングしていたのでECSなど使っていたのですが、この度Reactを利用することになり、 CloudFrontを使って配信するのがよいかなと思いまして勉強がてらReact+CloudFrontのCICDを行いました

ハンズオン形式で行えますのでぜひ試してみてください

開発環境

  • VSCode
  • WSL2 (Ubuntu 20.04)
  • Docker version 20.10.1
  • docker-compose version v2.2.3
  • git version 2.25.1

Reactの準備

以下のリポジトリをクローンしてきてください

https://github.com/jinwatanabe/react_cloudfront_cicd

そこにある/handsonフォルダでハンズオンを進めます。

$ cd handson
$ docker-compose run --rm app sh -c 'yarn install'
$ docker-compose up

localhost:3000にアクセスして以下の画面になれば成功です。

今回表示する内容を以下に変更します
app/src/App.tsxを修正します

app/src/App.tsx
import React from 'react';
import './App.css';

function App() {

  const clickBtn = (): void => {
    alert("Hello World!")
  }

  return (
    <button onClick={clickBtn}>Click!</button>
  );
}

export default App;

localhost:3000にアクセスしてボタンが表示されればOKです。クリックするとアラートでHello Worldと表示されます。

S3の作成

AWSコンソールからS3を開きます

まずはCloudFrontで配信するためのバケットを作ります。

「バケット作成」をクリックします
バケット名を「react-cicd-日付」にして「バケット作成」をクリックして作成します

次にCloudFrontのログ保存用バケットを作成します

バケット名 : react-cicd-logs-220815
ACL 有効
オブジェクト所有者 : オブジェクトライター

ACL有効にしないとCloudFrontのログを保存できないので注意してください

https://dev.classmethod.jp/articles/cloudfront-access-log-dont-choose-no-acl-s3-bucket/

「バケット作成」をクリックしたらログ用バケットの中にlogsというディレクトリを作成します

作成したバケット名をクリック
「フォルダの作成」をクリック

フォルダ名 : logs

「フォルダの作成」クリック

logsディレクトリが作成されました

2つのバケットが作成されていれば終了です

CloudFrontの設定

ここではRoute53でドメインとACMを取得していることを前提に説明します。取得は有料になりますので各自調べて行ってください

ここではour-aws.linkというドメインを取得して作業を進めていきます。

まずCloudFrontを開きます

「CloudFrontディストリビューションを作成」をクリック

以下の設定を行います

オリジンドメイン : 先ほど作成したCloudFront用バケット(react-cicd-220815)の名前が入ったものを選択

S3 バケットアクセス : ☑はい、OAI を使用します (バケットは CloudFront のみへのアクセスとなるように制限できます)

オリジンアクセスアイデンティティ : 新しいOAIを作成(作成したものを選択)

バケットポリシー : ☑はい、バケットポリシーを自動で更新します

ビューワープロトコルポリシー : Redirect HTTP to HTTPS
許可されたHTTPメソッド : GET, HEAD

代替えドメイン名(CNAME) : 追加→取得したドメイン(our-aws.link)
カスタムSSL証明書 : ACMで作成したものを選択

デフォルトルートオブジェクト : index.html
標準ログ記録 : オン
S3バケット : 作成したログ保存用バケット(react-cicd-logs-220815)
ログプレフィックス : logs

「ディストリビューションを作成」をクリックします

テストでアクセスする

お試しでアクセスしてみます
手元でindex.htmlを作成します

index.html
<h1>Hello CloudFront</h1>

このファイルをCloudFront用のS3にアップロードします

S3を開いてreact-cicd-220815をクリックします
「アップロード」をクリック
「ファイルを追加」をクリック
作成したindex.htmlを選択
「アップロード」をクリック

アップロードできたのでCloudFrontの作成したディストリビューションをクリックします

ディストリビューションドメイン名でアクセスします

このように表示されれば成功です

ドメインでアクセス

取得したドメインでアクセスできるように設定します
AWSコンソールからRoute53を開きます

左メニューから「ホストゾーン」をクリック
作成したドメイン名をクリック (ここではour-aws.link)
「レコードを作成」をクリック
「シンプルルーティング」を選択して「次へ」

「シンプルなレコードを定義」をクリック

値/トラフィックのルーティング先 : CloudFrontディストリビューションのエイリアス
ディストリビューションを選択 : 作成したディストリビューションのドメイン名

「シンプルなレコードを定義」をクリック
「レコードを作成」をクリック

our-aws.linkにアクセスすると先ほどと同じ画面が表示されます

CodeBuildを作成する

次にReactをGitにPushした際にCloudFrontの配信が更新されるようなCICDを設定していきます

まずはbuildspec.ymlを作成します

$ touch buildspec.yml
buildspec.yml
version: 0.2
phases:
    build:
        commands:
            - echo Build React...
            - docker-compose run --rm app sh -c 'yarn install'
            - docker-compose run --rm app npm run build
            - echo Finish Build!!

    post_build:
        commands:
            - echo Copy S3...
            - aws s3 sync app/build s3://CloudFront用のバケット名
            - echo Delete CloudFront cache...
            - aws cloudfront create-invalidation --distribution-id 作成したCloudFrontのID --paths "/index.html"
            - echo Success!
cache:
    paths:
        - app/node_modules/**/*

buildspecの一部は各自が設定した値に変更してください

ここではs3のバケット名はreact-cicd-220815
CloudFrontのIDはディストリビューションの一覧からわかります

CodeBuildではeactのビルドを行い、buildの中身を作成したバケットにコピーしています
そのあとでCloudFrontのキャッシュを削除しています

次にGithubのリポジトリを作成します
ここでは「react_cloudfront_cicd」で作成します

Pushまでを行います

$ git init
$ git add .
$ git commit -m "create repository"
$ git branch -M main
$ git remote add origin リポジトリURL
$ git push origin main

作成できました

次にAWSコンソールからCodeBuildを開きます

「ビルドプロジェクトを開く」をクリック

プロジェクト名 : react_cicd_220815
ソースプロバイダ : GitHub
リポジトリ : ☑GitHubアカウントのリポジトリ
GitHub リポジトリ: 作成したリポジトリ (react_cloudfront_cicd)

(GitHubと接続していない場合は接続が必要してください)

☑コードの変更がこのリポジトリにプッシュするたびに再構築する
イベントタイプ : プッシュ

オペレーションシステム : Ubuntu
ランタイム : Standard
イメージ : aws/codebuild/standard/6.0
イメージのバージョン : aws/codebuild/standard:6.0-22.06.30
特権付与 : ☑

「ビルドプロジェクトを作成する」をクリックして作成します

次に作成したロールにS3CloudFrontを操作できる権限を与えます

AWSコンソールからIAMを開きます
左メニューから「ロール」を開きます

作成したロール名をクリックします(CodeBuildの名前が入っているので検索しました)

「許可を追加」→「ポリシーをアタッチ」をクリックします

「AmaonS3FullAccess」を検索して☑

「CloudFrontFullAccess」を検索して☑

「ポリシーをアタッチ」をクリック

アタッチができたのでCodeBuildの作成したビルドプロジェクトを開きます

「ビルドを開始」をクリック
ビルドが成功すると以下のようなログがでます

our-aws.link(ドメイン)にアクセスしてみます

Reactが表示されました
ボタンを押すとアラートも表示されます

CICDの確認

app/src/App.tsxを以下に修正します
アラートのメッセージに「!」を加えました

app/src/App.tsx
import React from 'react';
import './App.css';

function App() {

  const clickBtn = (): void => {
    alert("Hello World!")
  }

  return (
    <button onClick={clickBtn}>Click!</button>
  );
}

export default App;

GitにプッシュしてCodeBuildを確認します

$ git add .
$ git commit -m "modify alert"
$ git push origin main

左メニューから「ビルドプロジェクト」をクリック
作成したプロジェクトをクリックするとPushしたことで新しいビルドが走っていることがわかります

ビルドが成功したらour-aws.linkを開くと更新されていることが確認できました

片付け

以下のリソースを削除してください

  • S3
  • CodeBuild
  • CloudWatchロググループ (CodeBuildで作成される)
  • Route53レコード
  • CloudFront
  • IAMロール (CodeBuildで作成)
  • IAMポリシー (CodeBuildで作成)

おわりに

前回Go(gin)とLambda(serverless framework)でCICDするでバックエンドのCICDを行い、今回はフロントエンドのCICDを行いましたが、ECSを使ってCICDするよりも直感的で簡単にできるような仕組みが整っているなと感じました

AWS初心者の方であればDockerを勉強してフロントエンドのCICDから挑戦してみるとよいのかもしれません

今回作成したリポジトリは以下にあります

https://github.com/jinwatanabe/react_cloudfront_cicd

参考

GitHubで編集を提案

Discussion