Rocky Linux 9 でプロダクション用に Node.js アプリケーションをセットアップする方法

紹介

Node.jsは、サーバーサイドおよびネットワーキングアプリケーションを構築するためのオープンソースのJavaScriptランタイム環境です。このプラットフォームはLinux、macOS、FreeBSD、およびWindowsで動作します。Node.jsアプリケーションをコマンドラインで実行できますが、このチュートリアルではそれらをサービスとして実行することに焦点を当てます。これにより、再起動や障害時に自動的に再起動し、本番環境で安全に使用できるようになります。

このチュートリアルでは、Rocky Linux 9サーバー上に本番用のNode.js環境をセットアップします。このサーバーはPM2によって管理されるNode.jsアプリケーションを実行し、Nginxリバースプロキシを介してアプリケーションへの安全なアクセスを提供します。NginxサーバーはLet’s Encryptが提供する無料の証明書を使用してHTTPSを提供します。

前提条件

このガイドでは、以下があると仮定しています:

前提条件を完了すると、ドメインのデフォルトのプレースホルダーページがhttps://example.com/で提供されます。

ステップ1 — Node.jsアプリケーションの作成

Hello Worldアプリケーションを記述し、HTTPリクエストに対して「Hello World」を返すようにします。このサンプルアプリケーションを使用すると、Node.jsを起動して実行できます。独自のアプリケーションに置き換えることもできますが、アプリケーションを適切なIPアドレスとポートでリッスンするように変更する必要があります。

Rocky Linux 9に付属しているデフォルトのテキストエディタはviです。viは非常に強力なテキストエディタですが、経験がないユーザーにとってはわかりにくい場合があります。Rocky Linux 9サーバーで構成ファイルを編集するのにより使いやすいエディターであるnanoなどをインストールすることを検討するかもしれません。

  1. sudo dnf install nano

今、nanoまたはお気に入りのテキストエディタを使用して、hello.jsというサンプルアプリケーションを作成してください。

  1. nano hello.js

次のコードをファイルに挿入してください:

~/hello.js
const http = require('http');

const hostname = 'localhost';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World!\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

ファイルを保存してエディタを終了します。 nanoを使用している場合は、Ctrl+Xを押し、プロンプトが表示されたらYを押し、次にEnterキーを押してください。

このNode.jsアプリケーションは、指定されたアドレス(localhost)とポート(3000)でリクエストを待ち受け、200のHTTP成功コードで「Hello World!」を返します。 localhostでリスニングしているため、リモートクライアントはアプリケーションに接続できません。

アプリケーションをテストするには、次のように入力してください:

  1. node hello.js

次の出力が表示されます:

Output
Server running at http://localhost:3000/

注意:この方法でNode.jsアプリケーションを実行すると、アプリケーションがCTRL+Cで終了されるまで、追加のコマンドがブロックされます。

アプリケーションをテストするには、サーバー上の別のターミナルセッションを開き、curlを使用してlocalhostに接続してください:

  1. curl http://localhost:3000

次の出力が表示される場合、アプリケーションは正しく動作し、正しいアドレスとポートでリスニングしています:

Output
Hello World!

期待される出力が表示されない場合は、Node.jsアプリケーションが実行され、適切なアドレスとポートでリスニングされていることを確認してください。

動作を確認したら、アプリケーションを(まだしていない場合は)CTRL+Cで終了してください。

ステップ2 — PM2のインストール

次に、Node.jsアプリケーションのプロセスマネージャであるPM2をインストールしましょう。PM2を使用すると、アプリケーションをデーモン化してバックグラウンドでサービスとして実行することができます。

サーバーに最新バージョンのPM2をインストールするには、npmを使用します:

  1. sudo npm install pm2@latest -g

-gオプションは、npmにモジュールをグローバルにインストールするように指示します。グローバルにインストールので、システム全体で利用できるようになります。

まず、pm2 startコマンドを使用してアプリケーションhello.jsをバックグラウンドで実行しましょう:

  1. pm2 start hello.js

これにより、アプリケーションがPM2のプロセスリストに追加され、アプリケーションを起動するたびに出力されます:

Output
... [PM2] Spawning PM2 daemon with pm2_home=/home/sammy/.pm2 [PM2] PM2 Successfully daemonized [PM2] Starting /home/sammy/hello.js in fork_mode (1 instance) [PM2] Done. ┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐ │ id │ name │ mode │ ↺ │ status │ cpu │ memory │ ├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤ │ 0 │ hello │ fork │ 0 │ online │ 0% │ 25.2mb │ └────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘

上記のように、PM2は自動的にApp name(ファイル名から.js拡張子を除いたもの)とPM2のidを割り当てます。 PM2は、プロセスのPID、現在のステータス、およびメモリ使用状況など、他の情報も管理します。

PM2の下で実行されているアプリケーションは、アプリケーションがクラッシュした場合や停止した場合に自動的に再起動されますが、startupサブコマンドを使用して、システムの起動時にアプリケーションを起動する追加の手順を実行できます。このサブコマンドは、PM2とその管理されたプロセスをサーバーブート時に起動するための起動スクリプトを生成および構成します:

  1. pm2 startup systemd
Output
… [PM2] To setup the Startup Script, copy/paste the following command: sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

提供されたコマンドをコピーして実行します(これはNode.jsツールをsudoとして実行する際の権限の問題を回避するためです)。

  1. sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy
Output
… [ 'systemctl enable pm2-sammy' ] [PM2] Writing init configuration in /etc/systemd/system/pm2-sammy.service [PM2] Making script booting at startup... [PM2] [-] Executing: systemctl enable pm2-sammy... Created symlink /etc/systemd/system/multi-user.target.wants/pm2-sammy.service → /etc/systemd/system/pm2-sammy.service. [PM2] [v] Command successfully executed. +---------------------------------------+ [PM2] Freeze a process list on reboot via: $ pm2 save [PM2] Remove init script via: $ pm2 unstartup systemd

今、Rocky LinuxのSELinuxセキュリティシステムと互換性があるように、新しく生成されたシステムサービスに編集を加える必要があります。お好きなテキストエディタ(例:nano)を使用して、/etc/systemd/system/pm2-sammy.serviceを開いてください:

  1. sudo nano /etc/systemd/system/pm2-sammy.service

構成ファイルの[Service]ブロックで、PIDFile設定の内容を以下に示すように/run/pm2.pidに置き換え、他のハイライトされたEnvironment行を追加してください:

/etc/systemd/system/pm2-sammy.service
[Unit]
Description=PM2 process manager
Documentation=https://pm2.keymetrics.io/
After=network.target

[Service]
Type=forking
User=sammy
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
Environment=PATH=/home/sammy/.local/bin:/home/sammy/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
Environment=PM2_HOME=/home/sammy/.pm2
PIDFile=/run/pm2.pid
Restart=on-failure
Environment=PM2_PID_FILE_PATH=/run/pm2.pid

ExecStart=/usr/local/lib/node_modules/pm2/bin/pm2 resurrect
ExecReload=/usr/local/lib/node_modules/pm2/bin/pm2 reload all
ExecStop=/usr/local/lib/node_modules/pm2/bin/pm2 kill

[Install]

ファイルを保存して閉じると、ユーザーの起動時にpm2を実行するsystemd unitが作成されます。このpm2インスタンスは、hello.jsを実行します。

systemctlでサービスを起動してください:

  1. sudo systemctl start pm2-sammy

systemdユニットのステータスを確認するには:

  1. systemctl status pm2-sammy

systemdの詳細な概要については、Systemd Essentials: Working with Services, Units, and the Journalを参照してください。

これまでに説明した内容に加えて、PM2にはアプリケーションを管理したり、情報を調べるための多くのサブコマンドがあります。

このコマンドでアプリケーションを停止します(PM2 App nameまたはidを指定します):

  1. pm2 stop app_name_or_id

アプリケーションを再起動します:

  1. pm2 restart app_name_or_id

PM2で現在管理されているアプリケーションをリストアップします:

  1. pm2 list

特定のアプリケーションに関する情報を取得します(App nameを使用します):

  1. pm2 info app_name

PM2プロセスモニターはmonitサブコマンドを使用して表示できます。これにより、アプリケーションの状態、CPU使用率、およびメモリ使用量が表示されます:

  1. pm2 monit

なお、pm2を引数なしで実行すると、例とともにヘルプページも表示されます。

Node.jsアプリケーションがPM2で実行され、管理されていると仮定して、リバースプロキシを設定しましょう。

ステップ3 — Nginxをリバースプロキシサーバーとして設定する

アプリケーションはlocalhostで実行され、リバースプロキシを介してユーザーがアクセスできるようにする必要があります。

前提チュートリアルで、Nginxの構成を/etc/nginx/conf.d/your_domain.confファイルに設定しました。このファイルを編集するために開いてください:

  1. sudo nano /etc/nginx/conf.d/your_domain.conf

serverブロック内には既存のlocation /ブロックがあるはずです。そのブロックの内容を次の構成で置き換えてください。アプリケーションが異なるポートでリッスンするように設定されている場合は、ハイライトされた部分を正しいポート番号に更新してください:

/etc/nginx/conf.d/your_domain.conf
server {
...
    location / {
        proxy_pass http://localhost: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;
    }
...
}

この設定は、サーバーがそのルートでリクエストに応答するように構成されています。サーバーがyour_domainで利用可能であると仮定すると、ウェブブラウザを介してhttps://your_domain/にアクセスすると、ポート3000localhostでリッスンしているhello.jsにリクエストが送信されます。

同じサーバーブロックに追加のlocationブロックを追加して、同じサーバー上の他のアプリケーションへのアクセスを提供できます。たとえば、ポート3001で別のNode.jsアプリケーションも実行している場合、次のlocationブロックを追加して、https://your_domain/app2を介してそのアプリケーションへのアクセスを許可できます:

/etc/nginx/conf.d/your_domain.conf — Optional
server {
...
    location /app2 {
        proxy_pass http://localhost:3001;
        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;
    }
...
}

アプリケーションのロケーションブロックを追加したら、ファイルを保存してエディターを終了します。

構文エラーを導入していないか確認するために、次のコマンドを入力してください:

  1. sudo nginx -t

Nginxを再起動します:

  1. sudo systemctl restart nginx

Node.jsアプリケーションが実行され、アプリケーションとNginxの構成が正しい場合、Nginxリバースプロキシを介してアプリケーションにアクセスできるはずです。サーバーのURL(公開IPアドレスまたはドメイン名)にアクセスして試してみてください。

結論

おめでとうございます!これで、Rocky Linux 9サーバー上でNode.jsアプリケーションがNginxリバースプロキシの背後で実行されています。このリバースプロキシの設定は、他のアプリケーションや共有したい静的ウェブコンテンツへのユーザーアクセスを柔軟に提供できます。

次に、Dockerを使用してNode.jsアプリケーションを構築する方法を調査してみてください。

Source:
https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-rocky-linux-9