綺麗に死ぬITエンジニア

Reactで作ったWebアプリをGitHubで管理してS3に自動デプロイする

2019-02-15

Reactで作成したフロントエンドのWebアプリを、GitHub上で管理して、masterブランチにコミットされた変更を自動でAmazon S3にデプロイ(適用)させる方法を解説します。

本記事では、S3をCloudFront経由でインターネット上へ公開し、名前解決をRoute 53で行う形とし、開発者はGitHub上のmasterブランチに変更をマージさえしてしまえば、後は勝手に公開されているソースコードが変更される仕組みにする方法を紹介します。

最も手間が少ない(と思われる)シンプルな構成を解説しますので、参考にしていただいて、後は自分のアプリケーションに合わせて自由に応用してもらえれば、と思います。

本記事で使うサービス

AWSの各サービスにかかる費用は各自でお調べください

構成

上記のサービスを使い、以下の構成を構築します。

構成図

開発者は、GitHubでソースコードの管理を行います。

事前に設定した特定のブランチに変更があると、Webhookでその変更を検知し、CodePipelineがCodeBuildへソースコード一式を渡します。

CodeBuildは受け取ったソースコード上でビルドコマンドを実行し、出来上がったファイル一式をCodePipelineへ再度返します。

その後、CodePipelineは受け取ったファイル一式をS3へ配置します。

インターネット利用者は、Route 53で名前解決を行い、CloudFrontへアクセスすることで、配置されたWebアプリを利用します。インターネット利用者は直接S3を参照できません。

ReactでWebアプリケーションを作成する

兎にも角にも、まずはWebアプリを作る必要があります。

今回はCreate React Appを使って導入される初期状態のReactで実施していきます。

npx create-react-app my-react-app --use-npm
cd my-react-app
npm start

上記のコマンドを実行して、Reactを導入、動作確認を行います。

今回はCodeBuildでnpmを使ってビルドするため、--use-npmオプションでnpmを使うことを強制しています(yarnを利用したい場合は、後ほど出てくるbuildspec.ymlyarnをインストールする必要が出てきます)。

上記のコマンドがちゃんと動けばとりあえずOKなので、そのソースコードを使って環境を構築していきます。

GitHubのリポジトリを作成

今導入したReactアプリケーションをGitHubで管理するために、まず任意の名称でリポジトリを作成します(作り方は割愛)。

リポジトリを作成するとき、オプションは選択せず、空のリポジトリを作成してください。

作成後、以下のコマンドでソースコード一式をプッシュします(usernameおよびrepositoryの部分は変更しましょう)。

git remote add origin git@github.com:username/repository.git
git push -u origin master

Create React Appで作成したソースコードは、すでにgit initgit commitされているので、重ねてする必要はありません。

buildspec.ymlの作成

プロジェクトのルートにbuildspec.ymlという名称で以下のテキストファイルを作成してください。

version: 0.2

phases:
  pre_build:
    commands:
      - if [ -e /tmp/node_modules.tar ]; then tar xf /tmp/node_modules.tar; fi
      - npm install
  build:
    commands:
      - npm run build
  post_build:
    commands:
      - tar cf /tmp/node_modules.tar node_modules
artifacts:
  files:
    - '**/*'
  base-directory: build
cache:
  paths:
    - /tmp/node_modules.tar

これは、CodeBuildによって実行されるビルド時のコマンドと、ビルド結果のファイルの位置やキャッシュの位置を示したものです。

CodeBuildはこれを読んで、ビルドを実行してくれます。

こちらの変更もコミット・プッシュしておきましょう。

git add buildspec.yml
git commit -m "create buildspec.yml"
git push -u origin master

S3の設定

先に、ビルドされたファイル一式を格納して公開するためのS3バケットを作成します。

AWSのコンソールにログインし、S3の画面を開きます。

「バケットを作成する」をクリックし、以降の画面で作成するバケットの設定を行っていきます。

s301

任意のバケット名を指定します。「オプションの設定」に関しては、環境に合わせ自由に設定します。

s302

今回はインターネットからS3に直接アクセスはしないので、「アクセス許可の設定」でパブリックアクセスは全面的に拒否する設定にしておきます(デフォルトのままでOK)。

この設定で、バケットを作成します。

CodePipelineの設定

AWSのコンソールにログインし、CodePipelineの画面を開きます。

「パイプラインの作成」をクリックし、以降の画面で自動ビルド・デプロイの設定を行っていきます。

codepipeline01

上記のようにパイプライン名に任意の名称を指定し、次の画面に進みます。

codepipeline02

ソースプロバイダに「GitHub」を選択し、「GitHubに接続」からGitHubにログインすると、上記のようにリポジトリとブランチを選択できるようになります。

変更を検知して自動デプロイしたいリポジトリとそのブランチを指定し、次の画面に進みます。

codepipeline03

ビルドプロバイダに「AWS CodeBuild」を選択し、「Create project」で新たなプロジェクトを作成します。

codepipeline04

Project nameに任意の名前を設定します。

codepipeline05

Operating systemで「Ubuntu」を選択、Runtimeで「Node.js」を選択、Runtime versionImage versionは各環境に合わせてビルド時に利用するべきNode.jsのバージョンを指定してください(通常は最も新しいもので良い)。

codepipeline06

buildspec.ymlを利用するので、「Use a buildspec file」のままで、buildspec.ymlの位置を変更する場合は、Buildspec nameでそのパスを指定します。

設定し終えたら、「Continue to CodePipeline」で次の画面に進みます。

codepipeline07

正常に設定し終わると、先ほどの画面に戻り、プロジェクト名に作成したプロジェクトが挿入されますので、次の画面に進みます。

codepipeline08

デプロイプロバイダに「Amazon S3」を選択し、先ほど作成したS3バケットを指定します。

「デプロイする前にファイルを展開する」チェックボックスにチェックを入れ、次の画面に進みます。

確認画面が出ますので、問題なければ「パイプラインの作成」をクリックし、パイプラインを作成します。

パイプラインを作成すると、作成したパイプラインの画面に飛び、最初のビルド・デプロイ処理が走ります。その流れは画面に表示され、途中で失敗した場合には画面でわかるようになっています。運用中に問題が発生した場合には、まずはこの画面を見るようにしましょう。

最初のビルド・デプロイ処理が終わると、指定したS3に出来上がったファイル一式が格納されますので、ここで一度、きちんと動作しているか確認しておきましょう。

CloudFrontの設定

S3を公開するにあたり、そのCDNとなるCloudFrontの設定を行います。

CloudFrontを利用しなくてもいい場合は、S3に対してWebサイトホスティングの設定とパブリックアクセスを許可する設定を行い、直接アクセスするようにしましょう。

AWSのコンソールにログインし、CloudFrontの画面を開きます。

「Create Distribution」をクリックし、「Web」のセクションの「Get Started」をクリックし、以降の画面でCloudFrontの設定を行っていきます。

Origin Settingsセクションで、次の設定を行います。

cloudfront01

Origin Domain Nameへ、先ほど作成したS3のバケットを指定します(フォーカスすると選択肢が出てきます)。

Restrict Bucket Accessを「Yes」にし、Origin Access Identityで「Create a New Identity」を選択し、Grant Read Permissions on Bucketで「Yes, Update Bucket Policy」を選択します。

また、Distribution Settingsセクションで、次の設定を行います。

Default Root Objectに「index.html」を設定しておきます。

Route 53で独自ドメインでの名前解決を行う場合は、Alternate Domain Names (CNAMEs)へ登録する予定のドメインを設定しておきます。

その他の設定は、ご自身のやりたい動作や環境に合わせて行ってください。ここでCloudFrontの細かい挙動の設定ができますが、個別の解説は長くなるので省略します。

例えば、HTTPSにしたい場合は、AWSで証明書の設定を行えば、AWSだけでHTTPSアクセスに対応させることもできます

特に動作が決まっていない場合は後からでも変更できるので、デフォルトのままでも大丈夫です。

設定値を入力したら「Create Distribution」をクリックし、ディストリビューションを作成します。

作成後、Stateが「In Progress」から「Deployed」になれば、作成完了です(少し時間がかかります)。

ここまで正常に設定し動作していれば、作成したディストリビューションのDomain Name*.cloudfront.net)へアクセスすると、Webアプリの確認ができます。

Route 53の設定

CloudFront(設定していない場合はS3)へアクセスするためのドメインを独自ドメインのものにするために、Route 53の設定を行います。

独自ドメインの取得方法Route 53へのHosted Zoneの設定はここでは解説しません。

AWSのコンソールにログインし、Route 53の画面を開きます。

設定するドメインのゾーンの画面を開き、「Create Record Set」をクリックします。

route5301

Nameに設定するドメイン、Typeに「A – IPv4 address」を選択し、Aliasを「Yes」にし、Alias Targetに先ほど作成したCloudFrontのディストリビューションを設定します。

Alias Targetは、フォーカスすると先ほど作成したCloudFrontのディストリビューションが表示されますので、それを選択します。それが表示されない場合、CloudFrontのAlternate Domain Names (CNAMEs)の設定がうまくできていない可能性があります。

route5302

CloudFrontでIPv6が有効になっている場合、上記のようにTypeが「AAAA – IPv6 address」の同じレコードも作成します。

Route 53の設定は以上です。少し待つと独自ドメインでアクセスできるようになるかと思います(DNSの反映には環境によって時間がかかる場合があります)。

動作確認

以上で、全ての設定が終了しました。

試しに何か変更を加えてGitHubにプッシュしてみましょう。自動でWebアプリケーションが更新されます。

なお、CloudFrontでデフォルトのまま設定している場合、即座に変更が確認できません(キャッシュされているため)。

Create React Appで生成されたアプリケーションを初期設定のままで使う場合、JSやCSSに変更があるとファイル名が変わるため、index.htmlだけキャッシュされないような設定をCloudFrontに追加すれば、変更が即座に反映されるような状態にすることも可能です。

一時的に変更されたことをすぐに確認したい場合は、CloudFrontのInvalidationでキャッシュを削除しましょう。

まとめ

上記で、ひとまずReactで作成したWebアプリを、GitHub上で管理して自動でAmazon S3にデプロイできるようになりました。

実際に運用する上では、CloudFrontで更なる細かい設定を行ったり、テストコードを追加してそれを通過した時だけビルドする等の処理を追加したりする必要が出てくるかと思いますので、それぞれの場面に合わせて更なる環境構築を進めてください。