EC2のNodeサーバーと連携するReactクライアントをS3にデプロイしてみる

AWS Summitに参加してからAWS関連でなんかしたいなあと思っていたので、 S3にReactで作ったクライアントを、EC2にNodeのサーバーを置いて、 簡単にアプリをデプロイしてみます:desktop:

以下の準備が整っていることを前提とします。 ・Reactでクライアントアプリを作っており、これと連携しているサーバーサイドも作られている。 ・EC2インスタンスを作成しており、sshでEC2に入れる。 ・作成したEC2のセキュリティグループのインバウンドの設定でhttpによる接続を受け付けられるようにしておく(これは後で設定しても良いですが)。

EC2にNodeで作ったサーバーを置く

まず、

  1. git
  2. nginx
  3. pip3を使うためにpython3
  4. pip3を使ってaws-cli
  5. nodeのlts版

をインストールします。 Nodeサーバーの場合なので、他の言語で書いていたりしたらそれに合わせてください。

$ yum update -y
$ yum install git -y
$ yum install nginx -y
$ yum install python3 -y
$ pip3 install aws-cli
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
$ vim ~/.bash_profile
$ source ~/.bash_profile
$ nvm install --lts
$ nvm use --lts
$ node -v

.bash_profileには以下を書き込みます。

# .bash_profile

# /home/production/のところは個別に設定してください。アプリケーションのディレクトリを置くところとかでいいと思います。
export NVM_DIR="/home/production/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"

次にサーバーのソースをクローンしてきます。 あと、nodeのプロセスを永続化するためにpm2を導入します。 pm2参考 => https://qiita.com/ikemura23/items/b3481393d4edca2d5188

$ git clone node-server
$ npm install -g pm2
$ cd node-server
$ pm2 start index.js --name node-server-on-ec2

EC2内で動いているサーバーにアクセスできるように、 外からやってきたhttpのリクエストをサーバーに転送してあげます。

ここで作ったindex.jsの設定ではlocalhost:3000をlistenしているので、 nginxでプロキシーの設定をして80番ポートにやってくるアクセスを3000番に転送します(localtion /を設定)。 nginxの設定参考 => https://qiita.com/morrr/items/7c97f0d2e46f7a8ec967 (プロキシーさせるためにもEC2へのhttpの接続をセキュリティグループで有効にしておくこと)

$ vim /etc/nginx/nginx.conf
# nginx.conf

server {
    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name  _;
    root         /usr/share/nginx/html;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    location / {
        proxy_pass http://localhost:3000;
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}

これでec2のパブリックIPに接続すると、EC2内で動いているnodeサーバーにアクセスできます。 エラーが出る場合、pm2やnginxの再起動などを行ってください。 セキュリティグループの設定も忘れずに:information_desk_person:

とりあえずここまででサーバー側のアプリをEC2に設置して、パブリックIPでアクセスできるようになります。

S3にReactで作ったクライアントを置く

1. バケット作成

S3でバケットを作成してください。 バケット名とリージョンを設定し、あとは基本的にデフォルトで良いです。 が、ブロックパブリックアクセスはオフにしておきます。

Screenshot 0031-07-21 at 12.36.35 PM.png

2. Static website hostingの設定

バケット作成後、Static website hostingを有効化するために、 Reactでbuildしたindex.htmlをインデックスドキュメントとして設定します。

Screenshot 0031-07-21 at 12.37.28 PM.png

3. バケットポリシーの設定

{
    "Version":"2012-10-17",
    "Statement":[{
        "Sid":"PublicReadForGetBucketObjects",
        "Effect":"Allow",
        "Principal": "*",
        "Action":["s3:GetObject"],
        "Resource":["arn:aws:s3:::example-bucket/*"]
    }]
}

静的ウェブサイトをセットアップする => https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/HostingWebsiteOnS3Setup.html

4. IAMでアクセス権限を持ったユーザーを作成する

IAMに入ってサイドペインからユーザーを選択、ユーザーを追加ボタンでユーザーを作成します。

Screenshot 0031-07-21 at 1.14.05 PM.png

ユーザー名を設定し、プログラムによるアクセスにチェックを入れます。

次に、既存のポリシーを直接アタッチでs3のアクセス権を選択し、これを付与します。

Screenshot 0031-07-21 at 1.15.18 PM.png

ここではAmazonS3FullAccessを選びますが、セキュリティなども考慮すればReadOnlyAccessの方が良かったり、時と場合によっては何が良いかが別れると思うので、その都度使い分けてください。

後の項目は基本デフォルトで良いです。 ユーザーを作成すると、AccessKeyIdとSecretAccessKeyの情報が記載されたCSVができると思うので、 その中にあるそれぞれの文字列を次に利用していきます。

5. EC2内でaws configureを行う

先ほど取得したIAMユーザーのAccessKeyIdとSecretAccessKeyをEC2にインストールしたawsコマンドで有効化します。

$ aws configure
AWS Access Key ID     **************
AWS Secret Access Key     **************
Default region name    ap-northeast-1
Default output format     json

AccessKeyId, SecretAccessKey, region, output formatの入力を促されるので、それぞれ入力します。 output formatはjsonで良いです。

6. ReactでbuildしたファイルをS3にアップロード

ここまでできたらあとはbuildしたファイルたちをS3にアップロードするだけです。 Reactプロジェクトの中に入って、以下のコマンドを打ちます。 バケット名は自分ので埋めてください。

$ aws s3 sync ./build s3://{バケット名} --acl public-read

.DS_StoreとかがS3に入るのが嫌なら、以下のオプションを追加して省くこともできます。

--exclude '*.DS_Store'

また、今回はEC2でIAMユーザーを一つだけ設定したかったので、aws configureを使いましたが、 複数のIAMユーザーが必要なら、~/.awsの中にあるconfigファイルおよびcredentialファイルにそれぞれの情報を書き込みます。

[default]となっているプロファイル(IAMユーザー)はaws configureで設定したものと同じになるようです。 [profile_name]としてプロファイルを複数作成していけます。

# ~/.aws/credentials

[default]
aws_access_key_id = XXXXXXXXXX
aws_secret_access_key = XXXXXXXXXX

[test]
aws_access_key_id = XXXXXXXXXX
aws_secret_access_key = XXXXXXXXXX

特定のIAMユーザーの権限でs3へアップロードを行いたい場合などは以下のようにコマンドを実行します。

$ aws s3 sync ./build s3://{バケット名} --acl public-read --profile {profile_name}

以上でデプロイが完了ですので、以下のようなURLでアプリケーションに接続できます。

http://{s3バケット名}.s3-website-ap-northeast-1.amazonaws.com

自分の作ったアプリが表示されれば成功です! EC2に置いてあるサーバーとも連携が取れているか確認してみてください。