AWS Summitに参加してからAWS関連でなんかしたいなあと思っていたので、
S3にReactで作ったクライアントを、EC2にNodeのサーバーを置いて、
簡単にアプリをデプロイしてみます
以下の準備が整っていることを前提とします。
・Reactでクライアントアプリを作っており、これと連携しているサーバーサイドも作られている。
・EC2インスタンスを作成しており、sshでEC2に入れる。
・作成したEC2のセキュリティグループのインバウンドの設定でhttpによる接続を受け付けられるようにしておく(これは後で設定しても良いですが)。
EC2にNodeで作ったサーバーを置く
まず、
- git
- nginx
- pip3を使うためにpython3
- pip3を使ってaws-cli
- 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には以下を書き込みます。
# /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
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の再起動などを行ってください。
セキュリティグループの設定も忘れずに
とりあえずここまででサーバー側のアプリをEC2に設置して、パブリックIPでアクセスできるようになります。
S3にReactで作ったクライアントを置く
1. バケット作成
S3でバケットを作成してください。
バケット名とリージョンを設定し、あとは基本的にデフォルトで良いです。
が、ブロックパブリックアクセスはオフにしておきます。
2. Static website hostingの設定
バケット作成後、Static website hostingを有効化するために、
Reactでbuildしたindex.htmlをインデックスドキュメントとして設定します。
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に入ってサイドペインからユーザーを選択、ユーザーを追加ボタンでユーザーを作成します。
ユーザー名を設定し、プログラムによるアクセスにチェックを入れます。
次に、既存のポリシーを直接アタッチでs3のアクセス権を選択し、これを付与します。
ここでは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]としてプロファイルを複数作成していけます。
[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に置いてあるサーバーとも連携が取れているか確認してみてください。