前書き

Node.jsは、サーバーサイドおよびネットワークアプリケーションを簡単に構築するためのオープンソースのJavascriptランタイム環境です。 このプラットフォームはLinux、OS X、FreeBSD、およびWindowsで動作し、そのアプリケーションはJavaScriptで記述されています。 Node.jsアプリケーションはコマンドラインで実行できますが、サービスとして実行する方法をお教えします。再起動または障害が発生すると自動的に再起動されるため、運用環境で使用できます。

このチュートリアルでは、2つのCentOS 7サーバーで構成される実稼働対応のNode.js環境のセットアップについて説明します。 1つのサーバーはPM2によって管理されるNode.jsアプリケーションを実行し、もう1つのサーバーはユーザーにアプリケーションサーバーへのNginxリバースプロキシを介してアプリケーションへのアクセスを提供します。

このチュートリアルのUbuntuバージョンはhttps://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-ubuntu-14-04にあります[ここに]。

前提条件

このガイドでは、2つのCentOS 7サーバー(同じネットワーク内のプライベートネットワーク)を使用しています。 プライベートネットワーキングは、作成時に新しいサーバーで設定できます( `+ Select additional options +`セクション)。 以下の名前でそれらを参照します。

  • * app *:Node.jsランタイム、Node.jsアプリケーション、およびPM2をインストールするサーバー。

  • * web *:Nginx Webサーバーをインストールするサーバー。アプリケーションへのリバースプロキシとして機能します。 ユーザーは、このサーバーのパブリックIPアドレスにアクセスしてNode.jsアプリケーションにアクセスします。

このガイドを始める前に、両方のサーバーで設定された `+ sudo +`権限を持つ通常の非rootユーザーが必要です。これは、サーバーにログインするユーザーです。 通常のユーザーアカウントを構成する方法については、https://www.digitalocean.com/community/tutorials/initial-server-setup-with-centos-7 [CentOS 7の初期サーバーセットアップガイド]をご覧ください。

  • app *サーバーで実行されるコマンド:

an_example_command_on_app
  • web *サーバーで実行されるコマンド:

an_example_command_on_web

このチュートリアルでは単一のサーバーを使用できますが、途中でいくつかの変更を行う必要があります。 localhost IPアドレス、つまり + 127.0.0.1 +、* app *サーバーのプライベートIPアドレスが使用されている場所。

以下は、このチュートリアルを実行した後のセットアップの図です。

image:https://assets.digitalocean.com/articles/nodejs/node_diagram.png [Node.jsアプリケーションへのリバースプロキシ]

パブリックIPアドレスの代わりにドメイン名を使用して* web *サーバーにアクセスできるようにする場合は、ドメイン名を購入してから次のチュートリアルに従ってください。

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

ステップ1-Node.jsのインストール

Node.jsの最新のLTSリリースを* app *サーバーにインストールします。

`+ sudo +`権限を持つ通常の非rootユーザーを使用して* app *サーバーにSSHで接続します。

  • app *サーバーで、 `+ curl +`を使用してhttps://github.com/nodesource/distributions[NodeSource] RPMリポジトリー構成ファイルをダウンロードしましょう。

curl -L -o nodesource_setup.sh https://rpm.nodesource.com/setup_10.x

`+ CURL +`はHTTPSプロトコルを使用してセットアップスクリプトをサーバーにダウンロードします。出力にはダウンロードに関連する情報が含まれます。

Output  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                Dload  Upload   Total   Spent    Left  Speed
100 11109  100 11109    0     0  70128      0 --:--:-- --:--:-- --:--:-- 70757

次に、スクリプトの内容を調べる必要があります。 次のコマンドは、サーバーコンソールでNodeSourceセットアップスクリプトを開きます。このスクリプトは、https://raw.githubusercontent.com/nodesource/distributions/master/rpm/setup_10.x [NodeSourceセットアップスクリプト]( NodeSource Distributions Githubリポジトリから)適切にダウンロードしたスクリプトを確認します。

vi nodesource_setup.sh

ファイルに満足したら、「+ quit 」に「:q 」と入力して「 vi +」を終了し、コマンドラインに戻ります。

次に、セットアップスクリプトを実行してNodeSource RPMリポジトリをインストールします。 これにより、 `+ yum +`パッケージマネージャー内からNodeSourceのリポジトリにアクセスできるようになります。

sudo -E bash nodesource_setup.sh

スクリプトは、参照用のセットアップに関する情報を出力します。

Output## Installing the NodeSource Node.js 10.x repo...

## Inspecting system...

+ rpm -q --whatprovides redhat-release || rpm -q --whatprovides centos-release || rpm -q --whatprovides cloudlinux-release || rpm -q --whatprovides sl-release
+ uname -m

## Confirming "el7-x86_64" is supported...

+ curl -sLf -o /dev/null 'https://rpm.nodesource.com/pub_10.x/el/7/x86_64/nodesource-release-el7-1.noarch.rpm'

## Downloading release setup RPM...

+ mktemp
+ curl -sL -o '/tmp/tmp.2aCcULVx8n' 'https://rpm.nodesource.com/pub_10.x/el/7/x86_64/nodesource-release-el7-1.noarch.rpm'

## Installing release setup RPM...

+ rpm -i --nosignature --force '/tmp/tmp.2aCcULVx8n'

## Cleaning up...

+ rm -f '/tmp/tmp.2aCcULVx8n'

## Checking for existing installations...

+ rpm -qa 'node|npm' | grep -v nodesource

## Run `sudo yum install -y nodejs` to install Node.js 10.x and npm.
## You may also need development tools to build native addons:
    sudo yum install gcc-c++ make
## To install the Yarn package manager, run:
    curl -sL https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
    sudo yum install yarn

Node.jsをインストールする前に、キャッシュされたすべての情報を `+ yum `から消去することが重要です。 キャッシュをクリアすると、 ` yum +`がネットワーク接続を使用して新しいNodeSourceリポジトリからNode.jsを取得するようになります(古いパッケージによる潜在的な競合を防ぐことができます)。

sudo yum clean all

次に、現在有効な `+ yum `リポジトリのすべてのメタデータをダウンロードして使用可能にします。 これにより、 ` yum +`クエリが可能な限り迅速に完了することが保証されます。

sudo yum makecache fast

`+ npm +`からネイティブアドオンをコンパイルしてインストールするには、ビルドツールもインストールする必要があります。

sudo yum install -y gcc-c++ make

これで、Node.jsパッケージの最新リリースをインストールできます。

sudo yum install -y nodejs

次のコマンドでバージョンを確認して、ノードがインストールされていることを確認します。

node -v

出力には、実行中のバージョン番号が表示されます。

Outputv

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

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

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

Node.jsアプリケーションでリバースプロキシサーバー(* web )からのリクエストを処理するため、サーバー間通信に app *サーバーのプライベートネットワークインターフェイスを使用します。 * app *サーバーのプライベートネットワークアドレスを検索します。

サーバーとしてDigitalOcean Dropletを使用している場合、_Metadata_サービスを介してサーバーのプライベートIPアドレスを検索できます。 * app *サーバーで、 `+ curl +`コマンドを使用してIPアドレスを今すぐ取得します。

curl -sw "\n" http://169.254.169.254/metadata/v1/interfaces/private/0/ipv4/address

Node.jsアプリケーションの構成に使用されるため、出力(プライベートIPアドレス)をコピーする必要があります。

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

vi hello.js

次のコードをファイルに挿入し、強調表示された両方の「+ APP_PRIVATE_IP_ADDRESS 」アイテムの代わりに* app *サーバーのプライベートIPアドレスを必ず置き換えてください。 必要に応じて、両方の場所で強調表示されているポート「+8080」を置き換えることもできます(必ず非管理ポートを使用してください。 `+ 1024 +`以上):

hello.js

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

保存して終了するには、単一のコマンドで「+ ESC 」を押して「-INSERT-」モードを終了し、続いて「:wq 」から「 write 」および「 quit +」を終了します。

このNode.jsアプリケーションは、指定されたIPアドレスとポートをリッスンし、HTTP成功コード「200」で「+ “Hello World” +」を返します。 これは、* web *サーバーなど、同じプライベートネットワーク上のサーバーからのみアプリケーションに到達できることを意味します。

アプリケーションが機能するかどうかをテストする場合は、* app *サーバーで次の `+ node +`コマンドを実行します。

node hello.js
  • web サーバーが app *上のNode.jsアプリケーションと通信できることを最初にテストすれば、多くのNginxデバッグを節約できます。

アプリケーションをテストするには、別のターミナルセッションを開き、* web *サーバーに接続します。 Webサーバーは同じプライベートネットワーク上にあるため、 `+ curl `を使用して* app *サーバーのプライベートIPアドレスに到達できるはずです。 * app *サーバーのプライベートIPアドレスを ` APP_PRIVATE_IP_ADDRESS +`に、ポートを変更した場合は必ず置き換えてください:

curl http://:

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

Node Application OutputHello World

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

  • app *サーバーで、 `+ CTRL + C +`を押してアプリケーションを強制終了します。

ステップ3-PM2のインストールと使用

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

Node.jsでインストールするNodeモジュール用のパッケージマネージャーであるNode Packaged Modules(NPM)を使用して、* app *サーバーにPM2をインストールします。 次のコマンドを使用して、PM2をインストールします。

sudo npm install [email protected] -g

PM2のいくつかの基本的な使用方法について説明します。

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

pm2 start

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

Output┌──────────┬────┬──────┬───────┬────────┬─────────┬────────┬─────────────┬──────────┐
│ App name │ id │ mode │ pid   │ status │ restart │ uptime │ memory      │ watching │
├──────────┼────┼──────┼───────┼────────┼─────────┼────────┼─────────────┼──────────┤
│ hello    │ 0  │ fork │ 30099 │ online │ 0       │ 0s     │ 14.227 MB   │ disabled │
└──────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────────────┴──────────┘

ご覧のように、PM2は_App name_(ファイル名に基づいて、拡張子「+ .js +」なし)とPM2 id_を自動的に割り当てます。 PM2は、プロセスの_PID、その現在のステータス、メモリ使用量などの他の情報も保持します。

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

`+ startup `サブコマンドは、サーバーの起動時にPM2とその管理対象プロセスを起動するための起動スクリプトを生成および構成します。 また、実行しているinitシステムを指定する必要があります。このシステムでは、 ` systemd +`です。

sudo pm2 startup systemd

次のような出力が表示されます。これは、PM2サービスがインストールされたことを示しています。

Output[PM2] Generating system init script in /etc/systemd/system/pm2.service
[PM2] Making script booting at startup...
[PM2] -systemd- Using the command:
     su root -c "pm2 dump && pm2 kill" && su root -c "systemctl daemon-reload && systemctl enable pm2 && systemctl start pm2"
[PM2] Dumping processes
[PM2] Stopping PM2...
[PM2] All processes have been stopped and deleted
[PM2] PM2 stopped
[PM2] Done.

PM2が起動時に起動するアプリケーションを認識できるようにするには、現在のプロセスリストを保存する必要があります。 リストを保存するには:

pm2 save

次のような出力が表示されます。これは、PM2プロセスリストが保存されたことを示しています。

Output[PM2] Saving current process list...
[PM2] Successfully saved in /home/deployer/.pm2/dump.pm2

これで、PM2が管理するアプリケーションが起動時に自動的に起動します。

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

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

pm2 stop

次のコマンドでアプリケーションを再起動します(PM2の「+ App name」または「+ id」を指定します):

pm2 restart

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

pm2 list

特定のアプリケーションに関する詳細情報は、 `+ info +`サブコマンドを使用して見つけることができます(PM2 _App name_または_id_を指定します)。

pm2 info

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

pm2 monit

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

ステップ4-Nginxリバースプロキシサーバーのセットアップ

アプリケーションが実行され、プライベートIPアドレスをリッスンしているので、ユーザーがアクセスする方法を設定する必要があります。 この目的のために、Nginx Webサーバーをリバースプロキシとして設定します。 このチュートリアルでは、Nginxサーバーをゼロからセットアップします。 すでにNginxサーバーをセットアップしている場合は、 `+ location +`ブロックを選択したサーバーブロックにコピーするだけです(場所がWebサーバーの既存のコンテンツと競合しないことを確認してください)。

  • web *サーバーで、yumを使用して `+ epel-release +`パッケージをインストールしましょう。

sudo yum install epel-release

次に、Nginxをインストールします。

sudo yum install nginx

Nginx構成ファイルを編集用に開きます。

sudo vi /etc/nginx/nginx.conf

最初に、デフォルトのサーバーブロック内で、「+ server_name +」が定義されている行を見つけます。 これは次のようになります。

nginx.confの抜粋-server_name(変更前)

server_name _;

サーバー名を更新して、アンダースコア( + _ +)を `+ server_name +`ディレクティブの独自のドメイン名(または、ドメインが設定されていない場合はIPアドレス)に置き換えます。

nginx.confの抜粋-server_name(後)

server_name ;

次に、同じデフォルトのサーバーブロック内で、「+ location / +」が定義されている行(通常はserver_nameの下の数行)を見つけます。 これは次のようになります。

nginx.confの抜粋-場所/(前)

       location / {
       }

これを次のコードブロックに置き換え、「+ APP_PRIVATE_IP_ADDRESS 」を* app *サーバーのプライベートIPアドレスに置き換えてください。 さらに、アプリケーションが別のポートでリッスンするように設定されている場合は、ポート( ` 8080 +`)を変更します。

/etc/nginx/nginx.conf抜粋-場所/(後)

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

これにより、ルートでリクエストに応答するように* web *サーバーが設定されます。 サーバーが「+ your-domain 」で利用可能であると仮定すると、ウェブブラウザ経由で「 http:// your-domain / 」にアクセスすると、ポート「+8080」でアプリケーションサーバーのプライベートIPアドレスにリクエストが送信されます。 Node.jsアプリケーションによって受信され、返信されます。

同じサーバーブロックに追加の「+ location 」ブロックを追加して、同じ* web *サーバー上の他のアプリケーションへのアクセスを提供できます。 たとえば、ポート ` 8081 `の* app *サーバーで別のNode.jsアプリケーションも実行している場合、このロケーションブロックを追加して、 ` http:// your-domain / app2 +を介したアクセスを許可できます。 `:

Nginx設定-追加の場所

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

アプリケーションのロケーションブロックの編集が完了したら、「+ ESC 」を押して「-INSERT-」モードを終了し、次に「:wq 」を押して「」に保存して終了しますwrite + + quit + `を1つのコマンドで。

  • web *サーバーで、Nginxを再起動します。

sudo systemctl start nginx

次に、サーバーが再起動するたびにNginxが実行されるようにします:

sudo systemctl enable nginx

`+ enable +`コマンドは以下の出力を提供するはずです

OutputCreated symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.

また、 `+ systemctl +`からNginxのステータスをリクエストすることで、Nginxが実行され有効になっていることを確認できます。

sudo systemctl status nginx

statusコマンドは、Nginxサービスの構成情報を出力します。

Output● nginx.service - The nginx HTTP and reverse proxy server
  Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
  Active: active (running) since Mon 2019-10-14 09:37:23 UTC; 3min 29s ago
Main PID: 12818 (nginx)
  CGroup: /system.slice/nginx.service
          ├─12818 nginx: master process /usr/sbin/nginx
          └─12819 nginx: worker process

Oct 14 09:37:23 centos-s-1vcpu-1gb-sgp1-01 systemd[1]: Starting The nginx HTTP and reverse proxy server...
Oct 14 09:37:23 centos-s-1vcpu-1gb-sgp1-01 nginx[12814]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Oct 14 09:37:23 centos-s-1vcpu-1gb-sgp1-01 nginx[12814]: nginx: configuration file /etc/nginx/nginx.conf test is successful
Oct 14 09:37:23 centos-s-1vcpu-1gb-sgp1-01 systemd[1]: Failed to read PID from file /run/nginx.pid: Invalid argument
Oct 14 09:37:23 centos-s-1vcpu-1gb-sgp1-01 systemd[1]: Started The nginx HTTP and reverse proxy server.

最後に、Nginxにhttps://selinuxproject.org/page/Main_Page[Security-Enhanced Linux](SELinux)を介してトラフィックを中継する機能を提供します。 SELinuxは、Linuxカーネルに必須アクセス制御(MAC)を実装するセキュリティレイヤーを提供します。 各オペレーティングシステムオブジェクト(プロセス、ファイル記述子、ファイルなど)には、オブジェクトが実行できる権限と操作を定義するSELinuxコンテキストのラベルが付けられています。

Nginxには `+ httpd_t `コンテキストのラベルが付けられているため、明示的に許可されない限り、SELinuxによってブロックされた多くの構成があります。 これを実証するには、次のコマンドを実行して、Nginxサービスに「 httpd_t +」というラベルが付けられていることを確認します。

ps -eZ

このコマンドはプロセスステータス情報を提供し、Nginx固有のプロセス情報を検索してラベルを表示します。 次のような方法で、 `+ httpd_t +`が表示されます。

Output...
system_u:system_r:httpd_t:s0    10208 ?        00:00:00 nginx
system_u:system_r:httpd_t:s0    10209 ?        00:00:00 nginx
...

次に、 + httpd_t + SELinuxラベルに関連するデフォルトのブール値のステータスを確認しましょう。 次のコマンドを実行して、この情報を表示できます。

getsebool -a

このチュートリアルでは、 `+ httpd +`関連のブール値のみに関心があります。

Output...
httpd_anon_write --> off
httpd_builtin_scripting --> on
httpd_can_check_spam --> off
httpd_can_connect_ftp --> off
httpd_can_connect_ldap --> off
httpd_can_connect_mythtv --> off
httpd_can_connect_zabbix --> off
httpd_can_network_connect --> off
httpd_can_network_connect_cobbler --> off
httpd_can_network_connect_db --> off
httpd_can_network_memcache --> off
httpd_can_network_relay --> off
httpd_can_sendmail --> off
httpd_dbus_avahi --> off
httpd_dbus_sssd --> off
httpd_dontaudit_search_dirs --> off
httpd_enable_cgi --> on
httpd_enable_ftp_server --> off
httpd_enable_homedirs --> off
httpd_execmem --> off
httpd_graceful_shutdown --> on
httpd_manage_ipa --> off
httpd_mod_auth_ntlm_winbind --> off
httpd_mod_auth_pam --> off
httpd_read_user_content --> off
httpd_run_ipa --> off
httpd_run_preupgrade --> off
httpd_run_stickshift --> off
httpd_serve_cobbler_files --> off
httpd_setrlimit --> off
httpd_ssi_exec --> off
httpd_sys_script_anon_write --> off
httpd_tmp_exec --> off
httpd_tty_comm --> off
httpd_unified --> off
httpd_use_cifs --> off
httpd_use_fusefs --> off
httpd_use_gpg --> off
httpd_use_nfs --> off
httpd_use_openstack --> off
httpd_use_sasl --> off
httpd_verify_dns --> off
...

特に注意すべき2つのブール値は、 `+ httpd_can_network_connect `と ` httpd_can_network_relay `です。 https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html-single/selinux_users_and_administrators_guide/index#sect-Managing_Confined_Services-The_Apache_HTTP_Server-Booleans[Redhat Documentation]は、各「 httpd +」の詳細を提供しますブール値とそれに関連する機能(各ブール値について詳しく知りたい場合)

...
httpd_can_network_connect: When disabled, this Boolean prevents HTTP scripts and modules from initiating a connection to a network or remote port. Enable this Boolean to allow this access.
httpd_can_network_relay: Enable this Boolean when httpd is being used as a forward or reverse proxy.
...

設定はトラフィックを中継するだけなので、SELinuxに `+ httpd `サーバー(この場合はNginx)がネットワークを使用して、設定したリバースプロキシ設定でトラフィックを中継できることを通知する必要があります。 変更が永続的であることを保証するために、 ` -P `フラグを使用します(このフラグを省略すると、サーバーの再起動時に ` httpd_can_network_relay +`がデフォルトの状態に戻ります)。

sudo setsebool -P httpd_can_network_relay on

Node.jsアプリケーションが実行中で、アプリケーションとNginxの構成が正しいと仮定すると、* web *サーバーのリバースプロキシ経由でアプリケーションにアクセスできるはずです。 *ウェブ*サーバーのURL(パブリックIPアドレスまたはドメイン名)にアクセスして試してください。

結論

これで、Node.jsアプリケーションがNginxリバースプロキシの背後で実行されました。 このリバースプロキシのセットアップは、ユーザーが共有したい他のアプリケーションまたは静的なWebコンテンツにアクセスできるように十分な柔軟性を備えています。

また、Webサーバーとユーザー間の送信を暗号化する場合は、https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-centos -7 [これは、HTTPS(TLS / SSL)サポートのセットアップを支援するチュートリアルです]。