nginx + node.js + pm2でアプリ向けのREST API環境を構築

nginx_nodejs_pm2前回の記事でWeb APIについて勉強し、モバイルアプリからのリクエストはNode.jsで捌くことにした。そのために環境を構築したときの覚書。

環境:CentOS 5.10, Node.js 0.10.21, nginx 1.4.3, pm2 0.6.5

 

< 2014/05/30 Modified >
CentOS6版も書いたのでそちらも参考に。

 


1.Node.jsをインストール

< 2013/12/09 Modified >
本番環境の場合は実行ユーザーで作成した方がいいので、この記事の最後の方を参照。

前の記事を参考にnvmでインストールする。

# nvm install v0.10.21
# nvm alias default 0.10.21

 


2.「Hello World」を作成

プロジェクトディレクトリに移動
# cd /home/project/

ExpressというNode.js向けのフレームワークをベースにする。

restifyというREST Webサービス用に特化したモジュールもあるけど、開発のスピードと下記ベンチマークを参考にExpressを選択。

expressjsの公式ドキュメント通りに「Hello World」を作る。
# vi package.json

{
  "name": "hello-world",
  "description": "hello world test app",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "express": "3.x"
  }
}

# npm install

# vi app.js

var express = require('express');
var app = express();

app.get('/', function(req, res){
  res.send('hello world');
});

app.listen(3000);

アプリ起動
# node app

別コンソールからアクセスして確認
# curl -i http://localhost:3000/

 


3.nginxを設定してブラウザから外部からアクセス

既にnginx + php-fpm + WordPressの環境があるので、リバースプロキシの設定をして外部から参照可能にする。

WordPressのサブディレクトリで動作させたかったので、ファイルが存在しなかったときのパーマリンクの動作を修正。

# vi /etc/nginx/conf.d/hoge.conf

server {
    listen       80;
    server_name  wordpress.hoge.net;

    ### Reverse Proxy for API
    location /api/ {
        rewrite ^/api/(.*)$ /$1 break;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_pass http://127.0.0.1:3000;
    }

    ### if the file is not found, forwarded to index.php (permalinks)
    set $rewrite_flg "false";
    if (!-e $request_filename) {
        set $rewrite_flg "true";
    }
    if ($uri ~ "^/api/") {
        set $rewrite_flg "false";
    }
    if ($rewrite_flg = "true") {
        rewrite ^/(.*)$ /index.php?q=$1 last;
    }
}

 

ブラウザからアクセスして確認
http://wordpress.hoge.net/api/

「hello world」が表示されるはず。

 


4.PM2をインストールしてnodeアプリをデーモン化

最後に常時起動させておくようにデーモン化する。

foreverよりpm2の方がクラスタリング(複数プロセスを使った負荷分散)も出来ておすすめらしい。

参考サイト

 

インストール
$ npm install -g pm2

すると下記エラー

gyp ERR! configure error
gyp ERR! stack Error: Python executable "python" is v2.4.3, which is not supported by gyp.
gyp ERR! stack You can pass the --python switch to point to Python >= v2.5.0 & < 3.0.0.

pythonのバージョンが古いらしい。メッセージにある通り「--python」オプションを利用してみる。

$ yum install python26
$ npm install -g pm2 --python=python26

起動する
$ pm2 start app.js -i max

Warningが出た。

PM2 [ERROR]  [Warning], you're using the 0.10.x node version, it's prefered that you switch to fork mode by adding the -x parameter.

node v0.10.xではstopしたときにポートを開放しないので、「fork mode」での動作がオススメらしい。詳しくは下記。

再起動
$ pm2 stop all
$ pm2 start app.js -x

動いているプロセスを表示
$ pm2 list

何が出来るかヘルプをみる
$ pm2 help

 

ファイルを監視して自動で再起動するのはまだ開発中ということなので、しばらくはnode-devを使って開発していた方がよさそう。

 

< 2013/12/09 Modified >
本番環境はrootで動かすと恐いのでnodejs実行用のユーザーを作成する。あとで権限の設定をするためにwwwというグループに所属させる。
# groupadd www
# useradd node -G www
# passwd node

所属グループの確認
# groups node

apacheユーザーの所属グループの変更
# usermod -G www apache

apacheユーザーだけが書き込み権限持っていた場所をwwwグループにも権限を与える
# chown apache.www -R /path/to/wordpress/wp-content/uploads
# chmod 775 -R /path/to/wordpress/wp-content/uploads

ユーザー切り替え
# su - node

ここからはnvmのインストールからやり直し。

ちなみにpm2は「-u」オプションで起動ユーザーを指定することができる。
$ pm2 -u apache start app.js -x

でもpm2で起動している場合「Permission denied」でファイルの書き込みに失敗する。node-devの場合は成功するのでまた今度調査。

 

< 2013/12/12 Modified >
nginx + php-fpmで動いている環境もuser=apche, group=wwwで動作するための設定を追記。(今まではuser=apche, group=apache)

php-fpmの設定
# vi /etc/php-fpm.d/www.conf

group = www

nginxの設定
# /etc/nginx/nginx.conf

user  apache www;

sessionの書き込みディレクトリの権限(/etc/php-fpm.d/www.confに記述)
# chown apache.www -R /var/lib/php/session/

※YUMでPHPが更新されたときに権限が変更されることがあったので注意。

phpMyAdminが下記エラーで起動しなくてハマった。

2013/12/12 18:44:47 [error] 3653#0: *188 readv() failed (104: Connection reset by peer) while reading upstream
2013/12/12 18:44:47 [error] 3653#0: *187 recv() failed (104: Connection reset by peer) while reading response header from upstream

念のためnginxのキャッシュディレクトリも権限を変更する
# chown apache.www -R /var/cache/nginx/*

 

< 2013/12/27 Modified >
接続元のIPアドレスを取得したかったので、X-Forwarded-Forの設定を追記。

 

 

< Related Posts >