32
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Nodejsアプリを自前サーバでサービス化する

Posted at

この記事の内容

  • Nodejsアプリをどうデプロイしようか
  • pm2というマネージャ
  • サービス化

どうサービスに乗せるのか

Nodejsを基盤とするWebアプリケーションはその守備範囲の広さから、アプリそのものが直接リクエストを受け付けることができます。
Javaや.NETではアプリケーションサーバ(GlassfishやIIS)がクライアントからのレスポンスを受け付けて、そこからレスポンスをアプリケーションに投げるわけですが、一方でNodejs Webアプリケーションはクライアントからのリクエストを直接受け取り、それを処理します。

Javaや.NETにおいてはアプリケーションサーバという階層があり、サービスとしての起動などはこの階層でよしなにやってくれます。
しかし、Nodejsではどうでしょう?
HerokuやOpenShiftなどのクラウドにデプロイしているから意識していない?
シェルスクリプトで cd ${applicationRoot}; node ./bin/app.js を実行させる? スマートじゃないですね。

サービス化するための選択肢

自前のサーバ上でNodejsアプリケーションをサービス化する試みはいくつかあって、

  • winser
    • windows上でサービス化するためのライブラリ
  • forever
    • linux/macOS上でのサービス化するためのデーモンマネージャ
  • pm2
    • Advanced, production process manager for Node.js

と言ったところがすぐ見つかるところ。

LinuxならPM2

Windows上でサービス化しようとするとwinserが唯一の選択肢、と言ったところですが、Linux/UNIXではforeverとpm2があります。
先発プロダクトがforeverで、後発がpm2です。
後発だけあって、pm2はかなり機能が充実しています。

  1. 自前ロードバランサ搭載で、クラスタ化可能
    • pm2自体がロードバランサとして動作することで、アプリケーションのクラスタリングを簡単に行うことができます。
      つまり、アプリケーション側でクラスタリングを実装する必要がないということ!
  2. 分散したログの集約閲覧
    • アプリのクラスタリングをするとノード単位にログが出力され、何が時系列に挙動を追跡するのが難しくなります。
      しかしpm2ではそれらログを統合し、一挙に確認できるようにしています。
  3. 設定ファイルで簡単起動
    • デプロイするサービスを設定ファイル(js/json/yml)に記述し、起動時に読み込めばもろもろの設定込みで起動ができます。
  4. 環境スイッチ付き
    • サービス設定ファイルに環境別の環境変数を設定することで、起動時にどの環境を使用するかスイッチすることができます。
  5. デプロイ機能つき
    • Gitのリポジトリを利用したリモートサーバへのデプロイ機能があります。

いろいろと機能があって全てを網羅するのは大変ですが、pm2を使用してNodejsアプリのサービス化を行ってみたいと思います。

pm2でサービス化

ここではトランスパイルしたファイルを使用し、Herokuなどではなく自前のサーバでサービス実行するまでの手順を説明します。
このセクションでは、以下のサーバ・所有者で実行することを目指します。

前提

  • バージョン
mw / lib version
node v9.0.0
pm2 2.7.2
  • サービス化環境
key value
サーバ sampleServ
デプロイ先 /opt/NodeApps/sample
実行ユーザ sample:sample。 sudoコマンド実行可能

デプロイ先/opt/NodeApps/sampleにはすでにアプリ資産がリリースされており、 npm install も完了している状況です。
本当はpm2のデプロイ機能も使いたかったけれど、サービス化するのが一杯一杯だったので。

サービス化手順

まずはpm2がなければ意味がないのでインストールします。

# npm install -g pm2

今度は実行ユーザにスイッチして、Nodejsのアプリケーションルートに移動します。pm2コマンドを実行するユーザがアプリの実行ユーザとなるので、
また、アプリケーション以下全てのファイルが実行ユーザの所有者である必要があります。

ではpm2で起動! となりますがちょっと待って。
設定ファイルを作りましょう。

pm2-service.json
{
    "apps": [
        {
            "name"        : "sample",
            "script"      : "./bin/application.js",
            "instances"  : 0,
            "watch"     : true,
            "exec_mode"  : "cluster",
            "source_map_support": true,
            "env": {
                "PORT": 8000,
                "NODE_ENV": "development"
            },
            "env_production" : {
                "NODE_ENV": "production"
            }
        }
    ]
}

pm2に吸い込ませる設定ファイルはappsプロパティの配列として定義します。これは複数のNodejsアプリを同一設定で呼び出すことができることを示しています。

それぞれのパラメータはpm2のリファレンスを見てもらうとして、特記すべきは exec_modeinstances ですね。
exec_mode: "cluster" を設定すればクラスタリングの設定となり、 instances : 0 とすればサーバが持つCPUコアの数だけノードを展開します(1以上の値を設定すれば使用するコア数=ノード数を設定できる)。

設定ファイルが書き上がってようやく起動です。

# cd /opt/NodeApps/sample
# pm2 start ./pm2-service.json --env production

pm2コマンドをsudoで実行すればrootが、sudoなしで実行すればカレントユーザーがサービスの実行ユーザとなります。
そして、 --env オプションが環境スイッチです。
pm2-service.json にある env.env_production が環境変数として設定されて実行します。
env.env はデフォルト設定、 env_* とあるものは --env に*を指定します。

e.g.) --env staging とすれば env.env_staging の設定が読み込まれます。

起動したしコレでOK、と思ってはいけません。pm2でのサービス起動の永続化には、 「現在の状況を記憶」 させる必要があります。

pm2では

  1. 最終的にあるべきサービス状態を構築
  2. 状態を記録し、永続化する

という流れでサービス化します。

# sudo pm2 startup [platform] -u sample
# pm2 save

[platform]は実行サーバのinitシステムによって変化します。

  • systemd
  • upstart
  • launchd
  • rcd

気をつけなければならないことは、実行ユーザをroot以外にする場合 -u オプションを忘れてはならないということです。
コレを忘れてしまうと、たとえ想定する実行ユーザで操作をしていたとしても、サーバ再起動をするとrootでアプリが動作します。

参考文献

PM2 - Advanced Node.js process manager
foerver
winser

32
43
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?