lxcficon.jpg Node.js server (執筆中)

元のページに戻る

Server side with JavaScript

JavaScriptでサーバーサイドのWebアプリを提供するサーバーを作りましょう。 LXCFによって、LXCコンテナを生成し、その中でNode.jsによるWebサーバをサービスします。

Node.jsとは、いわゆるサーバサイドで動作するJavaScriptのエンジンを含む言語環境です。 作成したプログラムは軽量で効率がよく、多数のネットワークからのリクエストを処理することができます。 また、ファイルやネットワークI/Oなどの機能を追加されています。

Node.jsでは、Webアプリを作成する場合、従来のPHP、JavaやPerlのように、ApacheやNginxのようなWebサーバーの中でプログラムを動かす形態とは異なります。 Node.jsで作成したプログラムがhttpのリクエストを捌いて効率よく負荷に強いWebサーバーとして働くのです。 しかし、零から高度なWebサーバーを作るのは大変です。そのため、いろいろなWebアプリケーションフレームワークがNode.jsには存在します。ここではその一つであるExpress.jsを使いましょう。

1. Node.js のサーバ構成

- OSは、Fedora 20を使います。
- Node.jsはソースからコンパイルして、インストールします。
- Node.jsのパッケージ管理ツールnpmを利用して、Node.jsのパッケージを管理します。
- npmを使って、WebサーバーのフレームワークであるExpress.jsをインストールします。
- LXCFでコンテナを一つ作ります。LXCFはJOINTモードにしておきます。
- コンテナの中でExpress.jsをWebサーバーとして使います。
- ネットワークの構成をVirt-manager経由から設定します。

2. Node.js のインストール

2.1 Node.js のソースからのインストール

ソースの入手

ソースを入手しましょう。
次のリンクにNode.jsのサイトがあります。

Downloadsを、押しましょう。

node_js_2.jpg

"Source Code"を選びます。するとソースのtarボールがダウンロードされます。

コンパイルとインストール

コンパイルにはgccが必要なので、入っていない場合はインストールしておいてください。

# yum install gcc

自分のホームディレクトリで解凍します。

$ tar zxvf node-v0.10.26.tar.gz

解凍したディレクトリに入ります。

$ cd node-v0.10.26

configureを実行。

$ ./configure

makeを実行。

$ make

ルートになってインストールします。

# make install

Node.jsの動作確認

JavaScriptがコマンドライン上でスクリプト言語のように使えます。

コマンド名は、nodeになります。前項でインストールが終わっていれば、/usr/local/binの下にnodeコマンドが入っています。

$ ls -l /usr/local/bin/node
-rwxrwxr-x. 1 root root 11078072  3月  5 08:57 /usr/local/bin/node

最初にhello,worldを表示しましょう。
以下をhello.jsに保存してください。

console.log('hello, world!');

実行します。

$ node hello.js
hello, world!

もう一つ試しましょう。
今度はフィボナッチ数を計算させます。
以下をfib.jsに保存してください。

function fib(n) {
	if (n <= 0) {
		return 0;
	} else if (n == 1) {
		return 1;
	} else {
		return fib(n-1)+fib(n-2);
	}
}

for (var i = 1; i < 10; i++) {
	console.log(fib(i));
}

実行します。

$ node fib.js
1
1
2
3
5
8
13
21
34

短時間で終了します。
node.jsは、高性能です。

2.2 Node.jsのパッケージ管理ツールnpm

Node.jsは、Webブラウザ上のJavaScriptの構文や記述が実行できるのに加えて、ファイルI/OやネットワークI/Oの機能が追加されています。 さらにノンブロッキングI/Oやイベントループの機能を持ち、高負荷にも耐えられるWebアプリケーションを作成しやすくできています。

しかし、それでもゼロから完全なWebサーバー機能を持つWebアプリケーションを作成するのは厄介ですね。 そこで、Node.jsのさまざまなアプリケーションやフレームワークのパッケージを集めたライブラリがネットワーク上で整備されています。

Node.jsをインストールすると、同時にnpmというツールがインストールされます。/usr/local/binの下を見てみましょう。

$ ls -l /usr/local/bin/npm
lrwxrwxrwx. 1 root root 38  3月  5 09:41 /usr/local/bin/npm -> ../lib/node_modules/npm/bin/npm-cli.js

これは、Node.jsのパッケージを、aptやyumのように扱うツールです。
以下を見てみるとさまざまなパッケージが整備されているのが見られます。

npm Node Packaged Modules https://www.npmjs.org/

Node.jsのWebアプリケーションのフレームワークをnpmによってインストールしましょう。

注) 学校内や社内などで、proxy経由で外部にアクセスする環境では次のようにproxyを設定してください。

  # npm config set proxy http://プロキシURI:ポート

2.3 Express.jsを使ったWebサーバー

Node.jsのWebアプリケーションのフレームワークにはさまざまなものがあります。 今回はその中でも人気のあるExpress.jsを使用します。

npmを使用すると、簡単にExpress.jsをインストールできます。 以下のように実行してください。

# npm -g install express

実行すると、必要なパッケージがダウンロードされ、インストールされます。

# npm -g install express
npm http GET https://registry.npmjs.org/express
npm http 304 https://registry.npmjs.org/express
npm http GET https://registry.npmjs.org/connect/2.14.1
npm http GET https://registry.npmjs.org/commander/1.3.2
npm http GET https://registry.npmjs.org/mkdirp/0.3.5
npm http GET https://registry.npmjs.org/range-parser/1.0.0
npm http GET https://registry.npmjs.org/buffer-crc32/0.2.1
npm http GET https://registry.npmjs.org/cookie/0.1.1
npm http GET https://registry.npmjs.org/fresh/0.2.2
  途中略

npm http 304 https://registry.npmjs.org/debuglog/0.0.2
npm http 304 https://registry.npmjs.org/core-util-is
/usr/local/bin/express -> /usr/local/lib/node_modules/express/bin/express
express@3.5.0 /usr/local/lib/node_modules/express
├── methods@0.1.0
├── merge-descriptors@0.0.2
├── cookie-signature@1.0.3
├── range-parser@1.0.0
├── fresh@0.2.2
├── debug@0.7.4
├── buffer-crc32@0.2.1
├── cookie@0.1.1
├── mkdirp@0.3.5
├── commander@1.3.2 (keypress@0.1.0)
├── send@0.2.0 (mime@1.2.11)
└── connect@2.14.1 (response-time@1.0.0, pause@0.0.1, connect-timeout@1.0.0, method-override@1.0.0, static-favicon@1.0.0, vhost@1.0.0, qs@0.6.6, basic-auth-connect@1.0.0, morgan@1.0.0, serve-static@1.0.2, bytes@0.2.1, raw-body@1.1.3, errorhandler@1.0.0, csurf@1.0.0, cookie-parser@1.0.1, compression@1.0.0, express-session@1.0.2, serve-index@1.0.1, multiparty@2.2.0)

さて、ここでインストールしたNode.js, Express.jsを、LXCFで生成したコンテナで実行しましょう。
次項からは、LXCFでコンテナを生成し、その中でExpress.jsのWebアプリケーションを作成します。 コンテナは複数作ることができ、それぞれで別のWebアプリケーションを作成して実行できます。

3. LXCFによるコンテナ作成

3.1 コンテナ作成

さて、ここでLXCのコンテナを一つ作りましょう。 LXCFは事前にLXCFのインストールに従ってインストールしておいてください。
rootでログインして次のように実行します。

# lxcf sysgen a-srv
ここで"a-srv”がコンテナ名です。コンテナ名には英数字、"-", または"_"が使えます。

コンテナが出来たら"lxcf list"で確認します。

# lxcf list 
Name	Mode    	State	  Path
------------------------------------------------------
a-srv	joint    	running	  /opt/lxcf/a-srv

出来たコンテナにはsshでloginできます。

# ssh a-srv
[root@a-srv ~]# 
プロンプトがa-srvにログインしたことを示しています。

なお、sshでlogin できない場合は数分待ってからもう一度sshでloginしてください。 sshサーバの起動に数分かかることがあるためです。

lxcf_a-srv1.jpg

ここで作成したa-srvコンテナは、ホストにインストールされたソフトウェアをすべて使用できます。
しかし、ipアドレスは固有の値が設定された、VMのような独立した環境です。

sshでloginしていろいろ試してみてください。VMとは異なり、ほとんどオーバーヘッドやレイテンシーを感じられないでしょう。

コンテナを削除するには、次のようにeraseコマンドを使用します。

# lxcf erase a-srv
erase /opt/lxcf/a-srv
erase /etc/lxcf/rsc/a-srv
erase ip address from /etc/hosts
erased  a-srv

3.2 ネットワークの作成

LXCFでは、デフォルトで設定されるネットワークは制御用のNAT接続です。
外部にネットワークサービスを提供するには、そのためのネットワークの設定の追加が必要です。 LXCFはlibvirt-lxcで動作しているため、ネットワークの設定については、virt-managerやvirshが使えます。

設定の仕方についてはvirt-managerやvirshのマニュアルを参照してください。

4. Express.js でWebアプリケーションを作成

4.1 LXCコンテナ上にExpressアプリの雛形を生成

この項では次のような作業を行います。

1) LXCコンテナの作成: コンテナ名 express-srv
2) sshでlogin
3) expressを動作させる新ユーザを作成: ユーザ名 express
4) expressの雛形アプリの生成: アプリ名 lxcfapp
5) HOSTからブラウザでアクセス確認
ProtWebApl.jpg

まず、Expressアプリを動作させるLXCコンテナを作成します。 ここでは、express-srvをコンテナ名とします。

# lxcf sysgen express-srv
Generating express-srv...
creating /opt/lxcf/express-srv...
creating /opt/lxcf/express-srv/proc...
creating /opt/lxcf/express-srv/etc...
creating /opt/lxcf/express-srv/run...
creating /opt/lxcf/express-srv/opt...
creating /opt/lxcf/express-srv/home...
creating /opt/lxcf/express-srv/root...
creating /opt/lxcf/express-srv/boot...
creating /opt/lxcf/express-srv/var...
......................
creating /opt/lxcf/express-srv/usr...
creating /opt/lxcf/express-srv/sbin...
creating /opt/lxcf/express-srv/bin...
creating /opt/lxcf/express-srv/lib...
creating /opt/lxcf/express-srv/lib64...
Setup completion of LXCF
ドメイン express-srv が /opt/lxcf/express-srv/etc/lxcf/rsc/express-srv/express-srv.xml から定義されました

express-srv is starting

LXCコンテナを作成して、1, 2分待つとコンテナ内のシステムがブートします。
sshdデーモンが自動的に起動し、sshで新しいコンテナにloginできるようになります。

# ssh express-srv
[root@express-srv ~]# 

プロンプトにコンテナ名が表示され、ssh loginできました。

次は、Webアプリのためのユーザーを登録し、作業ユーザを切り替えます。

[root@express-srv ~]# useradd express -m
[root@express-srv ~]# su - express
[express@express-srv ~]$

ここで作成したexpressユーザは、コンテナ内だけで有効です。HOST上には存在しないユーザであることに注意してください。 新しくnode.jsのexpressアプリを作っても、コンテナ固有のアプリであり、HOSTから独立します。

なお、すでに前章までにnode.jsはHOST上にインストールしています。
LXCFではHOST上にインストールしたプログラムは新しく作ったコンテナ上でもそのまま使うことができるのです。

さて、expressの雛形を作りましょう。
ここではlxcfappという名前でアプリケーションの雛形をつくります。
lxcfappディレクトリが作成されて、その下に雛形のファイルが配置されます。

[express@express-srv ~]$ express lxcfapp
   create : lxcfapp
   create : lxcfapp/package.json
   create : lxcfapp/app.js
   create : lxcfapp/public
   create : lxcfapp/public/javascripts
   create : lxcfapp/public/images
   create : lxcfapp/public/stylesheets
   create : lxcfapp/public/stylesheets/style.css
   create : lxcfapp/routes
   create : lxcfapp/routes/index.js
   create : lxcfapp/routes/user.js
   create : lxcfapp/views
   create : lxcfapp/views/layout.jade
   create : lxcfapp/views/index.jade

   install dependencies:
     $ cd lxcfapp && npm install

   run the app:
     $ node app

次に、lxcfappディレクトリに移動して、"npm install" を実行します。

[express@express-srv ~]$ cd lxcfapp
[express@express-srv lxcfapp]$ npm install
npm http GET https://registry.npmjs.org/express/3.5.0
npm http GET https://registry.npmjs.org/jade
npm http 200 https://registry.npmjs.org/express/3.5.0
npm http GET https://registry.npmjs.org/express/-/express-3.5.0.tgz
npm http 200 https://registry.npmjs.org/express/-/express-3.5.0.tgz
npm http 200 https://registry.npmjs.org/jade
npm http GET https://registry.npmjs.org/jade/-/jade-1.3.1.tgz
npm http 200 https://registry.npmjs.org/jade/-/jade-1.3.1.tgz

  <途中省略>

├── mkdirp@0.3.5
├── commander@1.3.2 (keypress@0.1.0)
├── send@0.2.0 (mime@1.2.11)
└── connect@2.14.1 (response-time@1.0.0, pause@0.0.1, method-override@1.0.0, connect-timeout@1.0.0, vhost@1.0.0, static-favicon@1.0.0, qs@0.6.6, basic-auth-connect@1.0.0, morgan@1.0.0, serve-static@1.0.2, bytes@0.2.1, raw-body@1.1.3, errorhandler@1.0.0, csurf@1.0.0, cookie-parser@1.0.1, express-session@1.0.2, compression@1.0.0, serve-index@1.0.1, multiparty@2.2.0)

installが終わると、lxcfappディレクトリの下にapp.jsというJavaScriptのプログラムが生成されました。
このapp.jsがアプリケーションの本体です。

[express@express-srv lxcfapp]$ ls
app.js  node_modules  package.json  public  routes  views

では、生成したlxcfappアプリケーションの雛形を実行してみましょう。
nodeコマンドで、app.jsを実行します。

[express@express-srv lxcfapp]$ node app.js
Express server listening on port 3000

port 3000で動きました。これでHOST上でfirefoxなどのブラウザから、"http://express-srv:3000"がアクセスできるはずです。
しかし、ちょっと待ってください。port 3000はおそらくLXCコンテナ内で動作するファイアーウォールでブロックされています。
コンテナ内のファイアーウォールのport 3000のブロックを解除しましょう。この操作は当然HOSTのファイアーウォールには影響しません。
コントロールC(^c)でいったん中断して、rootユーザに戻ってファイアーウォールのブロックを解除するコマンド(firewall-cmd)を実行します。
ブロックを解除したら元の場所にもどりましょう。

^c
[express@express-srv lxcfapp]$ exit
[root@express-srv ~]# firewall-cmd --permanent --add-port=3000/tcp
success
[root@express-srv ~]# su - express
[express@express-srv ~]$ cd lxcfapp
[express@express-srv lxcfapp]$ 

もう一度、"node app.js"を実行して作成したアプリ雛形を実行してみます。

[express@express-srv lxcfapp]$ node app.js
Express server listening on port 3000

HOST上でfirefoxを起動して、"http://express-srv:3000"にアクセスします。

ex-app.jpg

どうでしょうか。上のように見えたでしょうか?

なお、express-srvのアドレスはHOSTのNAT環境の中からしかアクセスできません。 HOST以外からアクセスできるようにするには、ネットワークの構成を追加・変更する必要があります。

4.2 Expressアプリの作成

4.3 LXCコンテナ上でのExpressアプリの実行

4.4 Expressアプリのクローン

4.5 ホストからLXCコンテナへのExpressアプリのコピー