0%

Koa入門 - Part1: io.js on Docker

Node.jsでAPIを作るときのフレームワークに何が良いかいろいろと試しています。Hapi.jsLoopBackSalis.jsactionhero.jsと試してみました。Koaは以前から気になっていましたが、ちょっと難しい印象があって避けていました。しかしES6ことECMAScript 2015がいよいよ承認されました。もたもたしているとES7やES8が来てしますので、もうクライアント側もサーバー側もES6に移行していかないといけないです。

ES6

ES6について全くの初心者なのですが、幸せになれそうな予感がするのでベットしようと思います。

ES6とio.js

サーバーサイドでES6やKoaを使う場合、io.jsの方が対応が進んでいます。そもそもio.jsが設立した原因の一つにNode.jsのV8とES6対応の開発方針への不満があったようです。ただ日本のNode.jsの広まりを考えるとサーバーサイドの開発言語としての採用に混乱を招いているようであまり良いことではありません。もっともio.jsがNode Foundationへの参加を決定して今後統合されていくみたいですが。

ES6と関数型プログラミング

言語仕様としてletconstなどで変数のスコープが安全に書けたり、パターンマッチングによる分配束縛(Destructuring)も使えます。

ようやくasyncif (error) return callback(error)のようなError-First Callbackに慣れてきた程度なのですが、ES6だともっとエレガントににコールバック地獄から抜けられるそうです。GeneratorPromiseなどまだ理解が必要なことが多いです。

またlodashを覚えてからNode.jsでも関数型プログラミング風に書けて読みやすくなりました。ES6ではArrow Functionsが標準で使えるので無名関数がもっと短く書けるようになります。

Destructuring、Arrow Function、Generator、Promiseを日本語に訳したりカタカナで表記するのも適切か悩むようになりました。明治時代の新漢語みたいにセンスある日本語ができれば良いのですが、そういう時代でもないですし。

Dockerでio.js環境をつくる

Dockerにはio.jsのiojsのオフィシャルイメージがあります。GitHubのリポジトリはdocker-iojsです。バージョンは6月にリリースされたばかりの2.3.0も用意されています。

Node.jsのオフィシャルイメージからONBUILD版を使うときは以下のように書いていました。

Dockerfile
FROM node:0.12-onbuild  
EXPOSE 3000

io.jsでも同じようにONBUILD版があります。

Dockerfile
FROM iojs:2.3-onbuild
EXPOSE 3000

ExpressでHello World

io.jsでKoaのプログラムを書く前に、お約束のExpressでHello Worldを動かしてみます。

プロジェクト

プロジェクトのディレクトリは以下のようになります。

$ cd ~/node_apps/docker_iojs
$ tree
.
├── Dockerfile
├── app.js
├── docker-compose.yml
└── package.json

app.jsはExpressのHello Worldを使います。

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

app.get('/', function (req, res) {
res.send('Hello World!');
});

var server = app.listen(3000, function () {

var host = server.address().address;
var port = server.address().port;

console.log('Example app listening at http://%s:%s', host, port);

});
package.json
{
"name": "iojs-express",
"description": "iojs-express",
"version": "0.0.1",
"private": true,
"dependencies": {
"express": "^4.13.0"
},
"scripts": {
"start": "node app.js"
}
}

Dockerfileのベースイメージはiojs:2.3-onbuildを使います。

Dockerfile
FROM iojs:2.3-onbuild
MAINTAINER Masato Shimizu <ma6ato@gmail.com>
EXPOSE 3000

docker-compose.ymlを記述します。ONBUILDを使っているのでカレントディレクトリはコンテナにマップしません。マウントするとカレントディレクトリにはDockerfileでnpm installしたnode_modulesが隠れてしまいます。

docker-compose.yml
express:
build: .
volumes:
- /etc/localtime:/etc/localtime:ro
ports:
- "3030:3000"

実行

Dockerイメージをビルドしてコンテナを起動します。io.jsでもコマンドはnodeコマンドです。バージョンは2.3.0です。Node.jsの方は同じnodeコマンドでも0.12.4なので混乱しそうです。

$ docker-compose build
$ docker-compose up
Creating dockeriojs_express_1...
Attaching to dockeriojs_express_1
express_1 | npm info it worked if it ends with ok
express_1 | npm info using npm@2.11.1
express_1 | npm info using node@v2.3.0
express_1 | npm info prestart iojs-express@0.0.1
express_1 | npm info start iojs-express@0.0.1
express_1 |
express_1 | > iojs-express@0.0.1 start /usr/src/app
express_1 | > node app.js
express_1 |
express_1 | Example app listening at http://:::3000

psで見るとDockerホストの3030ポートにマップされています。

docker-compose ps
Name Command State Ports
-----------------------------------------------------------------
dockeriojs_express_1 npm start Up 0.0.0.0:3030->3000/tcp

Docckerホストからcurlコマンドを使ってExpressの起動が確認できました。

$ curl localhost:3030
Hello World!