Ubuntu 16.04で実稼働用にNode.jsアプリケーションをセットアップする方法

前書き

Node.js is an open source JavaScript runtime environment for easily building server-side and networking applications. プラットフォームは、Linux、OS X、FreeBSD、およびWindowsで動作します。 Node.js applications can be run at the command line, but we’ll focus on running them as a service, so that they will automatically restart on reboot or failure, and can safely be used in a production environment.

このチュートリアルでは、単一のUbuntu 16.04サーバーでの実稼働対応Node.js環境のセットアップについて説明します。 このサーバーは、PM2によって管理されるNode.jsアプリケーションを実行し、ユーザーにNginxリバースプロキシを介したアプリケーションへの安全なアクセスを提供します。 Nginxサーバーは、Let’s Encryptが提供する無料の証明書を使用してHTTPSを提供します。

前提条件

このガイドでは、次のものがあることを前提としています。

前提条件を完了すると、サーバーがデフォルトのNginxプレースホルダーページをhttps://example.com/で提供するようになります。

サーバーにNode.jsランタイムをインストールすることから始めましょう。

Node.jsをインストールする

NodeSourceパッケージアーカイブを使用して、Node.jsの最新のLTSリリースをインストールします。

まず、NodeSource PPAをインストールして、そのコンテンツにアクセスする必要があります。 ホームディレクトリにいることを確認し、curlを使用してNode.js6.xアーカイブのインストールスクリプトを取得します。

cd ~
curl -sL https://deb.nodesource.com/setup_6.x -o nodesource_setup.sh

このスクリプトの内容は、nano(またはお好みのテキストエディター)で調べることができます。

nano nodesource_setup.sh

そして、sudoの下でスクリプトを実行します。

sudo bash nodesource_setup.sh

PPAが構成に追加され、ローカルパッケージキャッシュが自動的に更新されます。 nodesourceからセットアップスクリプトを実行した後、上記と同じ方法でNode.jsパッケージをインストールできます。

sudo apt-get install nodejs

nodejsパッケージにはnodejsバイナリとnpmが含まれているため、npmを個別にインストールする必要はありません。 ただし、一部のnpmパッケージ(ソースからコードをコンパイルする必要があるパッケージなど)を機能させるには、build-essentialパッケージをインストールする必要があります。

sudo apt-get install build-essential

Node.jsランタイムがインストールされ、アプリケーションを実行する準備ができました! Node.jsアプリケーションを作成しましょう。

[.note]#Note: NodeSource PPAからインストールする場合、Node.js実行可能ファイルはnodeではなくnodejsと呼ばれます。

Node.jsアプリケーションを作成する

HTTPリクエストに「HelloWorld」を返すだけのHello Worldアプリケーションを作成します。 これは、Node.jsのセットアップに役立つサンプルアプリケーションであり、独自のアプリケーションに置き換えることができます。適切なIPアドレスとポートでリッスンするようにアプリケーションを変更してください。

Hello World Code

まず、Node.jsアプリケーションを作成して開き、編集します。 このチュートリアルでは、nanoを使用して、hello.jsというサンプルアプリケーションを編集します。

cd ~
nano hello.js

次のコードをファイルに挿入します。 必要に応じて、両方の場所で強調表示されたポート8080を置き換えることができます(管理者以外のポートを使用してください。 1024以上):

hello.js

#!/usr/bin/env nodejs
var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(8080, 'localhost');
console.log('Server running at http://localhost:8080/');

ここで保存して終了します。

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

テストアプリケーション

アプリケーションをテストするには、hello.jsを実行可能としてマークします。

chmod +x ./hello.js

そして次のように実行します:

./hello.js
OutputServer running at http://localhost:8080/

[.note]#Note:この方法でNode.jsアプリケーションを実行すると、Ctrl-C
を押してアプリケーションが強制終了されるまで、追加のコマンドがブロックされます。

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

curl http://localhost:8080

次の出力が表示される場合、アプリケーションは適切に動作しており、適切なアドレスとポートでリッスンしています。

OutputHello World

適切な出力が表示されない場合は、Node.jsアプリケーションが実行中であり、適切なアドレスとポートでリッスンするように構成されていることを確認してください。

動作していることを確認したら、Ctrl+Cを押して、アプリケーションを強制終了します(まだ実行していない場合)。

PM2をインストールする

次に、Node.jsアプリケーションのプロセスマネージャーであるPM2をインストールします。 PM2は、アプリケーションを管理およびデーモン化する簡単な方法を提供します(サービスとしてバックグラウンドで実行します)。

Node.jsとともにインストールするNodeモジュールのパッケージマネージャーであるnpmを使用して、サーバーにPM2をインストールします。 次のコマンドを使用して、PM2をインストールします。

sudo npm install -g pm2

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

PM2でアプリケーションを管理する

PM2はシンプルで使いやすいです。 PM2のいくつかの基本的な使用方法について説明します。

アプリケーションを開始

最初に実行したいのは、pm2 startコマンドを使用して、アプリケーションhello.jsをバックグラウンドで実行することです。

pm2 start hello.js

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

Output[PM2] Spawning PM2 daemon
[PM2] PM2 Successfully daemonized
[PM2] Starting hello.js in fork_mode (1 instance)
[PM2] Done.
┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────────────┬──────────┐
│ App name │ id │ mode │ pid  │ status │ restart │ uptime │ memory      │ watching │
├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────────────┼──────────┤
│ hello    │ 0  │ fork │ 3524 │ online │ 0       │ 0s     │ 21.566 MB   │ disabled │
└──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────────────┴──────────┘
 Use `pm2 show ` to get more details about an app

ご覧のとおり、PM2は自動的にApp name(ファイル名に基づいて、.js拡張子なし)とPM2idを割り当てます。 PM2は、プロセスのPID、現在のステータス、メモリ使用量などの他の情報も保持します。

PM2で実行中のアプリケーションは、アプリケーションがクラッシュまたは強制終了すると自動的に再起動されますが、システムの起動時にアプリケーションを起動するために追加の手順を実行する必要があります(ブートまたはリブート)。 幸い、PM2には、これを行う簡単な方法であるstartupサブコマンドが用意されています。

startupサブコマンドは、サーバーの起動時にPM2とその管理対象プロセスを起動するための起動スクリプトを生成および構成します。

pm2 startup systemd

結果の出力の最後の行には、スーパーユーザー権限で実行する必要があるコマンドが含まれます。

Output[PM2] Init System found: systemd
[PM2] You have to run this command as root. Execute the following command:
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

生成されたコマンド(上記の強調表示された出力と同様ですが、sammyの代わりにユーザー名を使用)を実行して、PM2を起動時に開始するように設定します(独自の出力からコマンドを使用します)。

sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

これにより、起動時にユーザーに対してpm2を実行するsystemdunitが作成されます。 このpm2インスタンスは、次にhello.jsを実行します。 systemdユニットのステータスはsystemctlで確認できます。

systemctl status pm2-sammy

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

その他のPM2の使用法(オプション)

PM2には、アプリケーションに関する情報を管理または検索できる多くのサブコマンドがあります。 引数なしでpm2を実行すると、チュートリアルのこのセクションよりも詳細にPM2の使用法をカバーする使用例を含むヘルプページが表示されることに注意してください。

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

pm2 stop app_name_or_id

次のコマンドを使用してアプリケーションを再起動します(PM2App nameまたはidを指定します)。

pm2 restart app_name_or_id

現在PM2によって管理されているアプリケーションのリストは、listサブコマンドでも検索できます。

pm2 list

特定のアプリケーションの詳細については、infoサブコマンド(PM2App nameまたはidを指定)を使用して見つけることができます。

pm2 info example

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

pm2 monit

Node.jsアプリケーションが実行され、PM2によって管理されたので、リバースプロキシを設定しましょう。

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

アプリケーションが実行され、localhostをリッスンしているので、ユーザーがアプリケーションにアクセスする方法を設定する必要があります。 この目的のために、Nginx Webサーバーをリバースプロキシとして設定します。

前提条件のチュートリアルでは、/etc/nginx/sites-available/defaultファイルでNginx構成を設定します。 ファイルを編集用に開きます。

sudo nano /etc/nginx/sites-available/default

serverブロック内には、既存のlocation /ブロックが必要です。 そのブロックの内容を次の構成に置き換えます。 アプリケーションが別のポートでリッスンするように設定されている場合、強調表示された部分を正しいポート番号に更新します。

/etc/nginx/sites-available/default

. . .
    location / {
        proxy_pass http://localhost:8080;
        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;
    }
}

これにより、サーバーがルートで要求に応答するように構成されます。 サーバーがexample.comで利用可能であるとすると、Webブラウザーを介してhttps://example.com/にアクセスすると、hello.jsに要求が送信され、localhostでポート8080をリッスンします。

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

/etc/nginx/sites-available/default — Optional

    location /app2 {
        proxy_pass http://localhost:8081;
        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アドレスまたはドメイン名)にアクセスして試してください。

結論

おめでとうございます。 これで、Ubuntu 16.04サーバー上のNginxリバースプロキシの背後でNode.jsアプリケーションが実行されました。 このリバースプロキシのセットアップは、ユーザーが共有したい他のアプリケーションまたは静的なWebコンテンツにアクセスできるように十分な柔軟性を備えています。 Node.jsの開発を頑張ってください!

Related