紹介
Node.jsは、サーバーサイドおよびネットワーキングアプリケーションを構築するためのオープンソースのJavaScriptランタイム環境です。このプラットフォームはLinux、macOS、FreeBSD、およびWindowsで動作します。Node.jsアプリケーションをコマンドラインで実行できますが、このチュートリアルではそれらをサービスとして実行することに焦点を当てます。これにより、再起動や障害時に自動的に再起動し、本番環境で安全に使用できるようになります。
このチュートリアルでは、Rocky Linux 9サーバー上に本番用のNode.js環境をセットアップします。このサーバーはPM2によって管理されるNode.jsアプリケーションを実行し、Nginxリバースプロキシを介してアプリケーションへの安全なアクセスを提供します。NginxサーバーはLet’s Encryptが提供する無料の証明書を使用してHTTPSを提供します。
前提条件
このガイドでは、以下があると仮定しています:
- A Rocky Linux 9 server setup, as described in the initial server setup guide for Rocky Linux 9. You should have a non-root user with sudo privileges and an active firewall.
- A domain name pointed at your server’s public IP. This tutorial will use the domain name example.com throughout.
- Nginxがインストールされている(Rocky Linux 9におけるNginxのインストール方法についてはRocky Linux 9にNginxをインストールする方法を参照)。
- NginxはLet’s Encrypt証明書を使用してSSLで構成されています。Rocky Linux 9でLet’s Encryptを使用してNginxをセキュリティで保護する方法を説明します。
- サーバーにNode.jsがインストールされています。Rocky Linux 9にNode.jsをインストールする方法
前提条件を完了すると、ドメインのデフォルトのプレースホルダーページがhttps://example.com/
で提供されます。
ステップ1 — Node.jsアプリケーションの作成
Hello Worldアプリケーションを記述し、HTTPリクエストに対して「Hello World」を返すようにします。このサンプルアプリケーションを使用すると、Node.jsを起動して実行できます。独自のアプリケーションに置き換えることもできますが、アプリケーションを適切なIPアドレスとポートでリッスンするように変更する必要があります。
Rocky Linux 9に付属しているデフォルトのテキストエディタはvi
です。vi
は非常に強力なテキストエディタですが、経験がないユーザーにとってはわかりにくい場合があります。Rocky Linux 9サーバーで構成ファイルを編集するのにより使いやすいエディターであるnano
などをインストールすることを検討するかもしれません。
- sudo dnf install nano
今、nano
またはお気に入りのテキストエディタを使用して、hello.js
というサンプルアプリケーションを作成してください。
- nano 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
でリスニングしているため、リモートクライアントはアプリケーションに接続できません。
アプリケーションをテストするには、次のように入力してください:
- node hello.js
次の出力が表示されます:
OutputServer running at http://localhost:3000/
注意:この方法でNode.jsアプリケーションを実行すると、アプリケーションがCTRL+C
で終了されるまで、追加のコマンドがブロックされます。
アプリケーションをテストするには、サーバー上の別のターミナルセッションを開き、curl
を使用してlocalhost
に接続してください:
- curl http://localhost:3000
次の出力が表示される場合、アプリケーションは正しく動作し、正しいアドレスとポートでリスニングしています:
OutputHello World!
期待される出力が表示されない場合は、Node.jsアプリケーションが実行され、適切なアドレスとポートでリスニングされていることを確認してください。
動作を確認したら、アプリケーションを(まだしていない場合は)CTRL+C
で終了してください。
ステップ2 — PM2のインストール
次に、Node.jsアプリケーションのプロセスマネージャであるPM2をインストールしましょう。PM2を使用すると、アプリケーションをデーモン化してバックグラウンドでサービスとして実行することができます。
サーバーに最新バージョンのPM2をインストールするには、npm
を使用します:
- sudo npm install pm2@latest -g
-g
オプションは、npm
にモジュールをグローバルにインストールするように指示します。グローバルにインストールので、システム全体で利用できるようになります。
まず、pm2 start
コマンドを使用してアプリケーションhello.js
をバックグラウンドで実行しましょう:
- 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とその管理されたプロセスをサーバーブート時に起動するための起動スクリプトを生成および構成します:
- 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
として実行する際の権限の問題を回避するためです)。
- 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
を開いてください:
- sudo nano /etc/systemd/system/pm2-sammy.service
構成ファイルの[Service]
ブロックで、PIDFile
設定の内容を以下に示すように/run/pm2.pid
に置き換え、他のハイライトされたEnvironment
行を追加してください:
[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
でサービスを起動してください:
- sudo systemctl start pm2-sammy
systemdユニットのステータスを確認するには:
- systemctl status pm2-sammy
systemdの詳細な概要については、Systemd Essentials: Working with Services, Units, and the Journalを参照してください。
これまでに説明した内容に加えて、PM2にはアプリケーションを管理したり、情報を調べるための多くのサブコマンドがあります。
このコマンドでアプリケーションを停止します(PM2 App name
またはid
を指定します):
- pm2 stop app_name_or_id
アプリケーションを再起動します:
- pm2 restart app_name_or_id
PM2で現在管理されているアプリケーションをリストアップします:
- pm2 list
特定のアプリケーションに関する情報を取得します(App name
を使用します):
- pm2 info app_name
PM2プロセスモニターはmonit
サブコマンドを使用して表示できます。これにより、アプリケーションの状態、CPU使用率、およびメモリ使用量が表示されます:
- pm2 monit
なお、pm2
を引数なしで実行すると、例とともにヘルプページも表示されます。
Node.jsアプリケーションがPM2で実行され、管理されていると仮定して、リバースプロキシを設定しましょう。
ステップ3 — Nginxをリバースプロキシサーバーとして設定する
アプリケーションはlocalhost
で実行され、リバースプロキシを介してユーザーがアクセスできるようにする必要があります。
前提チュートリアルで、Nginxの構成を/etc/nginx/conf.d/your_domain.conf
ファイルに設定しました。このファイルを編集するために開いてください:
- sudo nano /etc/nginx/conf.d/your_domain.conf
server
ブロック内には既存のlocation /
ブロックがあるはずです。そのブロックの内容を次の構成で置き換えてください。アプリケーションが異なるポートでリッスンするように設定されている場合は、ハイライトされた部分を正しいポート番号に更新してください:
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/
にアクセスすると、ポート3000
でlocalhost
でリッスンしているhello.js
にリクエストが送信されます。
同じサーバーブロックに追加のlocation
ブロックを追加して、同じサーバー上の他のアプリケーションへのアクセスを提供できます。たとえば、ポート3001
で別のNode.jsアプリケーションも実行している場合、次のlocation
ブロックを追加して、https://your_domain/app2
を介してそのアプリケーションへのアクセスを許可できます:
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;
}
...
}
アプリケーションのロケーションブロックを追加したら、ファイルを保存してエディターを終了します。
構文エラーを導入していないか確認するために、次のコマンドを入力してください:
- sudo nginx -t
Nginxを再起動します:
- sudo systemctl restart nginx
Node.jsアプリケーションが実行され、アプリケーションとNginxの構成が正しい場合、Nginxリバースプロキシを介してアプリケーションにアクセスできるはずです。サーバーのURL(公開IPアドレスまたはドメイン名)にアクセスして試してみてください。
結論
おめでとうございます!これで、Rocky Linux 9サーバー上でNode.jsアプリケーションがNginxリバースプロキシの背後で実行されています。このリバースプロキシの設定は、他のアプリケーションや共有したい静的ウェブコンテンツへのユーザーアクセスを柔軟に提供できます。
次に、Dockerを使用してNode.jsアプリケーションを構築する方法を調査してみてください。