デプロイ(Next)
Next.jsのリリースは同じrailsのec2に乗せる方法採用する。 こうすることで、運用費を割安にすることができるし、仕組みも簡単になる。
AWSではこういったフレームワークをAmplifyでホスティングし配信する仕組みがある。 いくつかの手順を踏めば、簡単にデプロイとホスティングができるので、良いことには良いのだが、 Amplifyとec2の2台が稼働する仕組みとなり、ランニングコストがかさむ。
そもそも、ampifyはサーバレス的な構成で利用されるので、ec2を利用しているのならば、そのまま同じサーバに乗せるのが吉である。
デプロイ環境の構築
まずはデプロイファイルを作成するところから始める。
Next.jsプロジェクトに移動し、deploy.pyを作成する。
touch deploy.py
中身をこの様にする。app_nameは各々のnext.jsのプロジェクト名にする。
import sys
import sysrsync
import paramiko
from os import environ
IP_ADDRESS = environ['IP_ADDRESS']
USER_NAME = environ["USER_NAME"]
KEY_FILENAME =environ["KEY_FILENAME"]
sysrsync.run(source='../app_name/',
destination='/usr/share/nginx/app_name/',
destination_ssh=USER_NAME+'@'+IP_ADDRESS,
options=['-a','--rsync-path="sudo rsync"'],
exclusions=['.git','.next','.gitignore','.envrc','.prettierignore','.prettierrc.yml','.DS_Store','README.md', "deploy.py","node_modules"],
private_key=KEY_FILENAME)
print("Project was syncted")
# sshクライアントの作成
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.WarningPolicy())
client.load_system_host_keys()
# 上記で設定したIPアドレス、ユーザー名、キーファイルを渡す
client.connect(IP_ADDRESS,
username=USER_NAME,
key_filename=KEY_FILENAME,
timeout=5.0)
print("SSH was connected")
try:
client.exec_command('sudo chown -R ec2-user:nginx /usr/share/nginx/app_name')
print("Change the rails project owers")
except Exception as ee:
sys.stderr.write(str(ee) + "\n")
# ssh接続断
client.close()
del client
print("Deployed!")
.envrcを作成する。
touch .envrc
sshに関する情報を.envrcに書き込む。 これはRailsでやった時と同じだから、そちらを丸コピしても良い。
export IP_ADDRESS="ec2のIPアドレス"
export USER_NAME="ec2-user"
export KEY_FILENAME='絶対パスでsshキーのパスを指定'
環境変数を読み込む
direnv allow
.gitignoreを開いて.envrcをgitの管理下から除外する。
.envrc
試しにデプロイしてみる。
正常に動作すれば、ec2の/usr/share/nginx/app_nameにデプロイされる。
python3 deploy.py
git add .
git commit -m "Create a deploy file"
ec2サーバでnodeのセットアップ
Railsをインストールしたec2サーバにはまだnodeが導入されていない。
AWSのnodeの導入方法を参考にして、インストールする。
Amazon EC2 インスタンスでの Node.js のセットアップ
sshしたサーバで下のコマンドを実行。
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
bashを再読み込みし、nvmコマンドを利用できる様にする。
source ~/.bash_profile
ローカルと同じnodeのバージョンを利用したい。ローカルでは17.9.0なのでそれをnvm経由でインストールする。
nvm install 17.9.0
nvm use 17.9.0
そしたら、next.jsプロジェクトに移動して
cd /usr/share/nginx/app_name
モジュールをインストール。
npm install
ビルドして。
npm run build
とりあえず、3000番ポートでアクセスできるか試す。
npm run start
ec2のセキュリティグループでprivate httpにポート番号3000番のHTTPアクセスを加える。
private httpのセキュリティグループを選び、編集する。

新しくルールを加え、カスタムTCPで3000番を選び、マイIPを選び、保存する。

ec2のIPアドレスに直でアクセスする。
http://ec2のIPアドレス:3000/
この様に表示されればうまく動いている。

Next.jsのデーモナイズ
npm startコマンドはデーモン化されていないので、実行を止めると、アプリケーションサーバも止まる。 railsのunicornと同じように、デーモナイズして止まらない様にする。
node系のプロセス管理はどうやらpm2というが有名らしいので、それを利用する。
最初に、next.jsプロジェクト内で、pm2の設定ファイルを作成する。
touch ecosystem.config.js
中身をこうする。
module.exports = {
apps: [
{
name: 'next',
script: 'npm',
args: 'start',
},
],
}
サーバにデプロイする。
python3 deploy.py
ec2サーバでpm2コマンドをインストール
npm install pm2@latest -g
インストールが終わったら、サーバのnext.jsのプロジェクトに移動して、以下のコマンドで起動する。
pm2 start ecosystem.config.js
プロセスを確認するときはこのコマンド。
pm2 ls
プロセスを止めるときは。
pm2 delete next
リスタートするときは。
pm2 restart next
単純に実行した時と同じように、ポート3000番で起動するので、IPアドレス直打ちでアクセスできるか試す。

作成したpm2の設定ファイルをコミットしておく。
git add .
git commit -m "Create a pm2 configuration file"
Route53でドメイン割り振る
railsにbeta-api.xxx.comのようなドメインを割り振ったように、next.jsにもbeta.xxx.comというドメインを割り振る。
ec2のパブリックIPアドレスをコピーしておく。

route53のコンソールに移動して、ドメインを選び、新しくレコードを作成する。

サブドメインはbetaにして、コピーしたIPアドレスを貼り付け、レコードを作成する。

しばらく待って、登録したURLでhttp://beta.xxx.comアクセスしてみる。
nginxではこのドメインでの処理を記述していないので、nginxの404が返ってくるはずである。

新しくnext.jsのnginx設定を作成する。
sudo touch /etc/nginx/conf.d/next.conf
以下を書き込む。 localhostの3000番にリダイレクトする設定。 server_nameは取得しているドメインに変更する。
server {
server_name beta.xxx.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_pass http://localhost:3000;
}
}
再起動して、
sudo systemctl restart nginx
route53で割り当てたURLにアクセスする。
http://beta.xxx.com
こんなふうにアクセスできる。

nextjsをsslにする
これも、railsの時と同じようにcertbotを利用すれば簡単にssl化できる。 始める前に、httpとhttpsが世界中からアクセスが可能になっているかを確認する。
サーバーでcertbotを起動する。
sudo certbot --nginx --register-unsafely-without-email
ドメインの選択が表示されるので、beta. の方を数字の番号で選ぶ。
Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: beta.alice.com
2: beta-api.alice.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):
処理が終わったら、next.jsのURLもsslになる。
https://beta.alice.com

next.jsをrails apiにつなぐ
このNext.jsのテンプレートではあらかじめ本番環境でエンドポイントがlocalhostから別の場所になりそうなところは環境変数にしてある。
具体的にはpages/sign_up.jsx とlib/api/client.jsに含まれているNEXT_PUBLIC_で始まるのがそれである。
本番で利用する環境変数の設定は簡単で.env.productionというファイルを作り、そこに変数を宣言すれば良い。
これは、npm startが実行された時に読み込まれるので、ローカルの開発環境では利用されない。
next.jsのプロジェクトルートでファイルを作成する。
touch .env.production
中身をこのようにする。xxx.comの箇所は取得したドメインに変更する。
NEXT_PUBLIC_API_ROOT="https://beta-api.xxxx.com"
NEXT_PUBLIC_CONFIRMATION_URL="https://beta.xxxx.com/confirmation"
NEXT_PUBLIC_RESET_PASSWORD_URL="https://beta.xxxx.com/reset_password"
デプロイする。
python3 deploy.py
ec2サーバに移動して、buildして、pm2を再起動する。
cd /usr/share/nginx/nextjsのプロジェクト名
pm2 delete next
npm run build
pm2 start ecosystem.config.js
これで、サービスが利用できるはずである。 サインアップページからユーザー認証を行い、ログインして投稿してみる。
最後に本番環境の環境変数をコミットして、ベータデプロイ完了
git add .
git commit -m "Create a production environment file"