Next.js13とsystemdと永続化

Nextjs

はじめに

今回は、下図のNginx、Next.jsとの連携までを作ります。

Next.js 13をsystemdで永続化するための方法を調べました。
nvmなどの設定が不要な方は「systemdの設定ファイル」の項目をご覧ください。

Debianの場合は「/var/www/.npm」ディレクトリを作成する必要があります。
また、実際に運用するためにNginxをリバースプロキシに設定します。

環境

- Debian bullseye 64bit
- nvm 0.39.5
- Node.js 20.6.0
- React 18.2.0
- Next.js 13.4.19
- Nginx 1.18.0

nvm(Node Version Manager)のインストール

Node.jsの仮想環境を構築するためにnvmをインストールします。
また、ホームディレクトリに「.nvm」が作成されるので環境変数を反映させます。

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash


. ~/.bashrc

または

source ~/.bashrc

nodeのインストール

インストール可能なNode.jsの一覧を表示させ、希望のバージョンを指定してインストールします。
最新版をインストールします。

nvm ls-remote
nvm install v20.6.0

または

nvm install node

その他のコマンドです。

nodeのパスを確認する
which npm

nodeのバージョン切り替え
nvm use v19.9.0

nodeのバージョンを確認する
node -v

アプリの作成

Next.jsのアプリを作成します。
アプリはTypeScriptを有効にしてインストールします。

mkdir /home/www/frontend
cd /home/www/frontend
npx create-next-app --ts .

その他に必要なものをインストールします。

npm install axios

起動テスト

正常にインストールされたことをWebブラウザでアクセスして確認します。

cd /home/www/frontend
npm run dev

足りないディレクトリの作成

素の状態でsystemdを使って永続化、起動すると下記のエラーが出力されます。

 xx月 xx xx:51:04 xxxxx npm[22222]: npm ERR! code EACCES
 xx月 xx xx:51:04 xxxxx npm[22222]: npm ERR! syscall mkdir
 xx月 xx xx:51:04 xxxxx npm[22222]: npm ERR! path /var/www/.npm
 xx月 xx xx:51:04 xxxxx npm[22222]: npm ERR! errno -13
 xx月 xx xx:51:04 xxxxx npm[22222]: npm ERR!
 xx月 xx xx:51:04 xxxxx npm[22222]: npm ERR! Your cache folder contains root-owned files, due to a bug in
 xx月 xx xx:51:04 xxxxx npm[22222]: npm ERR! previous versions of npm which has since been addressed.
 xx月 xx xx:51:04 xxxxx npm[22222]: npm ERR!
 xx月 xx xx:51:04 xxxxx npm[22222]: npm ERR! To permanently fix this problem, please run:
 xx月 xx xx:51:04 xxxxx npm[22222]: npm ERR!   sudo chown -R 33:33 "/var/www/.npm"
 xx月 xx xx:51:04 xxxxx npm[22222]: npm ERR! Log files were not written due to an error writing to the directory: /var/www/.npm/_logs
 xx月 xx xx:51:04 xxxxx npm[22222]: npm ERR! You can rerun the command with `--loglevel=verbose` to see the logs in your terminal
 xx月 xx xx:51:04 xxxxx systemd[1]: nextjs-frontend.service: Control process exited, code=exited, status=243/CREDENTIALS

メッセージにあるように、足りないディレクトリを作成します。

sudo mkdir  /var/www/.npm
sudo chown -R 33:33 /var/www/.npm

systemdの設定ファイル

systemdの設定ファイルを作成します。

sudo vi /etc/systemd/system/nextjs-frontend.service

設定ファイルは以下のようになります。
ポート番号は「Environment=PORT=3000」で指定します。

また、「ExecStartPre」でdaemonを起動する前に実行するプログラムを記述します。
毎回buildするので、実行に時間が掛かります。
不要ならば「#」でコメントしてください。

npmコマンドは、nvmでインストールしたホームディレクトリにあるものを指定します。

./src/app以下のファイルを修正した場合は「npm run build」が必要です。

 [Unit]
Description=Next.js frontend
After=syslog.target network.target

[Service]
Description=Brain Project for Next.js frontend
After=syslog.target network.target

[Service]
ExecStart = /home/xxxxx/.nvm/versions/node/v20.6.0/bin/npm run start
WorkingDirectory = /home/www/wsgi/ds/frontend

# ポート番号
Environment=PORT=3000

# 起動前にinstallとbuildを行う。
ExecStartPre=/home/xxxxx/.nvm/versions/node/v20.6.0/bin/npm install
ExecStartPre=/home/xxxxx/.nvm/versions/node/v20.6.0/bin/npm run build

Restart = always

#Type = simple
#NotifyAccess = all

# 実行ユーザとグループ
User = www-data
Group = www-data

# syslogにログを記録する。
StandardError = syslog

[Install]
WantedBy=multi-user.target

Daemonの有効化と起動

Daemonを起動します。
systemdの設定ファイルを修正したらreloadが必要です。

sudo systemctl enable nextjs-frontend

sudo systemctl daemon-reload

sudo systemctl start nextjs-frontend

エラーの場合は、下記コマンドで原因を探る。

sudo journalctl -xe
sudo systemctl status nextjs-frontend.service

ポート番号の重複エラーの対処

Daemonを停止してもプロセスが残る場合があり、以下のエラーが表示されます。
ポート番号が3000の場合です。

Error: listen EADDRINUSE: address already in use :::3000

ポート番号の重複がある場合はプロセス番号を表示させてkillします。

sudo lsof -i :3000

sudo kill -9 xxxx

Nginxをリバースプロキシにする

設定ファイルを作成します。

cd /etc/nginx/sites-available
sudo vi frontend

内容は下記となります。
locationを「/front」など「/」以外にするとエラーになるので原因を調査中です。

server {
    listen 80;
    server_name 192.168.10.2;
    charset utf-8;

    # max upload size
    client_max_body_size 5000M;

    #allow 192.168.10.8;
    #allow 192.168.10.0/24;
    #deny all;
    allow all;

    index index.html index.htm;
    root /home/www/frontend;

    location /_next/static {
        alias /home/www/frontend/.next/static;
        add_header Cache-Control "public, max-age=3600, immutable";
    }

    location / {
        proxy_pass http://192.168.10.2:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;

        add_header Cache-Control "public, max-age=3600";
    }

    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml app
}

シンボリックリンクを作成してNginxを再起動します。

cd /etc/nginx/sites-enabled

sudo ln -s /etc/nginx/sites-available/frontend.

sudo systemctl restart nginx

Webブラウザで「http://192.168.10.2/」にアクセスして、「npm run dev」で「http://192.168.10.2:3000/」にアクセスしたときと同じ画面が表示されるかテストします。

Comments