Skip to main content

デプロイ(Next)

Next.jsのリリースは同じrailsのec2に乗せる方法採用する。 こうすることで、運用費を割安にすることができるし、仕組みも簡単になる。

AWSではこういったフレームワークをAmplifyでホスティングし配信する仕組みがある。 いくつかの手順を踏めば、簡単にデプロイとホスティングができるので、良いことには良いのだが、 Amplifyとec2の2台が稼働する仕組みとなり、ランニングコストがかさむ。

そもそも、ampifyはサーバレス的な構成で利用されるので、ec2を利用しているのならば、そのまま同じサーバに乗せるのが吉である。

デプロイ環境の構築

まずはデプロイファイルを作成するところから始める。

Next.jsプロジェクトに移動し、deploy.pyを作成する。

touch deploy.py

中身をこの様にする。app_nameは各々のnext.jsのプロジェクト名にする。

deploy.py
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の管理下から除外する。

.gitignore
.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のセキュリティグループを選び、編集する。

edit

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

port 3000

ec2のIPアドレスに直でアクセスする。

http://ec2のIPアドレス:3000/

この様に表示されればうまく動いている。

ipaccess

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アドレス直打ちでアクセスできるか試す。

front

作成したpm2の設定ファイルをコミットしておく。

git add .
git commit -m "Create a pm2 configuration file"

Route53でドメイン割り振る

railsにbeta-api.xxx.comのようなドメインを割り振ったように、next.jsにもbeta.xxx.comというドメインを割り振る。

ec2のパブリックIPアドレスをコピーしておく。

copy-ip

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

select domain

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

beta sub domain

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

beta alice

新しく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

こんなふうにアクセスできる。

domain

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

to ssl

next.jsをrails apiにつなぐ

このNext.jsのテンプレートではあらかじめ本番環境でエンドポイントがlocalhostから別の場所になりそうなところは環境変数にしてある。 具体的にはpages/sign_up.jsxlib/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"