Node.js ウェブ・アプリの Docker 化

この例のゴールは、 Dockerfile を使い、親イメージから自分の Docker イメージを構築できるようにする方法を理解します。ここでは CentOS 上で簡単な Node.js の hello world ウェブ・アプリケーションを実行します。ソースコード全体は https://github.com/enokd/docker-node-hello/ から入手できます。

Node.js アプリの作成

まず、全てのファイルを置く src ディレクトリを作成します。それから package.json ファイルを作成し、アプリケーションと依存関係について記述します。

{
  "name": "docker-centos-hello",
  "private": true,
  "version": "0.0.1",
  "description": "Node.js Hello world app on CentOS using docker",
  "author": "Daniel Gasienica <daniel@gasienica.ch>",
  "dependencies": {
    "express": "3.2.4"
  }
}

次に index.js ファイルを作成し、ウェブアプリが Express.js フレームワークを使うように定義します。

var express = require('express');

// Constants
var PORT = 8080;

// App
var app = express();
app.get('/', function (req, res) {
  res.send('Hello world\n');
});

app.listen(PORT);
console.log('Running on http://localhost:' + PORT);

次のステップでは、Docker が CentOS コンテナの中で、どのようにこのアプリを実行するかを理解していきます。まず、自分のアプリを動かす Docker イメージを作成します。

Dockerfile の作成

Dockerfile という名称の空ファイルを作成します。

touch Dockerfile

好みのエディタで Dockerfile を開きます。

自分のイメージの構築に使いたい親イメージを定義します。ここでは Docker Hub 上で利用可能な CentOS (タグ: centos6 )を使います。

FROM    centos:centos6

Node.js アプリを作るのために、CentOS イメージ上に Node.js と npm をインストールします。アプリケーションの実行には Node.js が必要です。また、 package.json で定義したアプリケーションをインストールするために npm も必要です。CentOS 用の適切なパッケージをインストールするため、 Node.js wiki の指示に従って作業します。

# Enable Extra Packages for Enterprise Linux (EPEL) for CentOS
RUN     yum install -y epel-release
# Install Node.js and npm
RUN     yum install -y nodejs npm

npm バイナリでアプリケーションの依存関係をインストールします。

# Install app dependencies
COPY package.json /src/package.json
RUN cd /src; npm install --production

アプリケーションのソースコードを Docker イメージに取り込むため、 COPY 命令を使います。

# Bundle app source
COPY . /src

アプリケーションはポート 8080 を利用のため、 EXPOSE 命令を使い docker デーモンがポートを割り当てるようにします。

EXPOSE  8080

最後にあと少し、実行時にアプリケーションを実行できるよう CMD 命令でコマンドを定義します。例えば node と、アプリケーション、例えば src/index.js を指定します(ソースファイルは前の手順でコンテナに加えていました)。

CMD ["node", "/src/index.js"]

これで Dockerfile は次のようになります。

FROM    centos:centos6

# Enable Extra Packages for Enterprise Linux (EPEL) for CentOS
RUN     yum install -y epel-release
# Install Node.js and npm
RUN     yum install -y nodejs npm

# Install app dependencies
COPY package.json /src/package.json
RUN cd /src; npm install --production

# Bundle app source
COPY . /src

EXPOSE  8080
CMD ["node", "/src/index.js"]

イメージを構築

Dockerfile のあるディレクトリに移動し、Docker イメージを構築するため次のコマンドを実行します。 -t フラグを使いイメージにタグを付ければ、あとから docker images コマンドで簡単に探せます。

$ docker build -t <自分のユーザ名>/centos-node-hello .

作成したイメージは、Docker のイメージ一覧に表示されます。

$ docker images

# Example
REPOSITORY                          TAG        ID              CREATED
centos                              centos6    539c0211cd76    8 weeks ago
<your username>/centos-node-hello   latest     d64d3505b0d2    2 hours ago

イメージの実行

イメージに -d を付けて実行したら、コンテナはデタッチド・モードで動作します。これは、コンテナをバックグラウンドで動作するものです。 -p フラグで、コンテナ内のプライベートなポートを公開ポートに渡します。

$ docker run -p 49160:8080 -d <自分のユーザ名>/centos-node-hello

アプリケーションの出力を表示します。

# Get container ID
$ docker ps

# Print app output
$ docker logs <container id>

# Example
Running on http://localhost:8080

テスト

アプリケーションをテストするには、Docker でアプリケーションにポートを割り当てます。

$ docker ps

# Example
ID            IMAGE                                     COMMAND              ...   PORTS
ecce33b30ebf  <your username>/centos-node-hello:latest  node /src/index.js         49160->8080

この例は、Docker はコンテナのポート 8080 をポート 49160 に割り当てます。

これで curl を使ってアプリケーションを呼び出せます(インストールの必要があれば sudo apt-get install curl を実行します。 )。

$ curl -i localhost:49160

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 12
Date: Sun, 02 Jun 2013 03:53:22 GMT
Connection: keep-alive

Hello world

OS X 上で Docker Machine を使っている場合は、ポートが実際に割り当てられているのは Docker ホストの VM 側であり、次のコマンドを使う必要があります。

$ curl $(docker-machine ip VM_NAME):49160

私たちはこのチュートリアルが、Docker 上で Node.js と CentOS を動かす手助けになるのを望みます。全てのソースコードは https://github.com/enokd/docker-node-hello/ にあります。

参考

Dockerizing a Node.js web app
https://docs.docker.com/engine/examples/nodejs_web_app/