Passenger Nginx と Node.jsではマルチポートでLISTENするアプリをうまくリバースプロキシできませんでした。簡単なNode.jsアプリをNginxを動かすだけでも時間がかかってしまうので、もっと勉強しないといけないです。
今回の目的は、xio.ioを使い、IPアドレスだけでWildcard DNS
のテストをすることです。Namecheapで安いドメイン名を買えますが、開発や社内利用の場合、ローカルにDNSサーバーを用意しなくても名前解決ができるのはとても便利です。
HTTP Routing
したいDockerコンテナの各ポートを、Node.jsのアプリで見立て、動かしてみます。
Dockerfile
最初に完成したDockerfileです。phusion/baseimage
を使います。
~/docker_apps/xipio/DockerfileFROM phusion/baseimage:0.9.11
ENV HOME /root
CMD ["/sbin/my_init"]
RUN /etc/my_init.d/00_regen_ssh_host_keys.sh
ADD my_key.pub /tmp/your_key RUN cat /tmp/your_key >> /root/.ssh/authorized_keys && rm -f /tmp/your_key
RUN sed -i~ -e 's/archive.ubuntu.com/ftp.jaist.ac.jp/' /etc/apt/sources.list \ && apt-get update
RUN apt-get install -y software-properties-common RUN add-apt-repository ppa:chris-lea/node.js RUN apt-get -yqq update
RUN apt-get install -y nodejs nginx
RUN rm -rf /etc/nginx/sites-enabled/default ADD webapp.conf /etc/nginx/sites-enabled/ RUN mkdir -p /srv/www/webapp/ ADD app.js /srv/www/webapp/ ADD sv /etc/service
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
runitの設定ファイル
Node.jsアプリのrunitの設定ファイルです。
~/docker_apps/xipio/sv/nodejs/run#!/bin/sh
cd /srv/www/webapp exec 2>&1 exec chpst -U www-data node app.js > /var/log/nodejs.log 2>&1
|
runitのNginxです。
~/docker_apps/xipio/sv/nginx/run#!/bin/bash
exec 2>&1
exec /usr/sbin/nginx -g "daemon off;"
|
svlogdを使ったログの設定です。
~/docker_apps/xipio/sv/nginx/log/run#!/bin/sh
service=$(basename $(dirname $(pwd))) logdir="/var/log/${service}" mkdir -p ${logdir} exec 2>&1 exec /usr/bin/svlogd -tt ${logdir}
|
Node.jsアプリ
Node.jsで同一プロセスで複数ポートをLISTENするサンプルがCan HttpServer listen to multiple ports?にあったのでサンプルに使ってみます。
~/docker_apps/xipio/app.jsvar http = require('http') , servers = [] , port = 8000;
function addServer(fn) { var s = http.createServer(fn); s.listen(port); servers.push(s); port += 1; }
addServer(function(req,resp){ resp.writeHead(200); resp.end('hi'); });
addServer(function(req,resp){ resp.writeHead(200); resp.end('hello'); });
addServer(function(req,resp){ resp.writeHead(200); resp.end('howdy'); });
|
xip.io用のNginxの設定
xip.ipのURLにポート番号を埋め込み、server_name
の正規表現で動的にパースしてポート番号を抽出します。
リクエストに応じて動的にプロキシー先のポートを指定する仕組みになります。
~/docker_apps/xipio/webapp.confserver { listen 80; server_name ~^p(?<port_name>\d+)\.(.*)\.xip\.io$;
location / { proxy_set_header host $host; proxy_set_header x-real-ip $remote_addr; proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:$port_name; } }
|
build
Dockerイメージをビルドします。
$ cd ~/docker_apps/xipio $ docker build -t masato/xipio .
|
Node.jsを直接コールする
Node.jsのポートマップを3つ指定して、Dockerコンテナを実行します。
$ docker run --rm -i -p 8000:8000 -p 8001:8001 -p 8002:8002 -t masato/xipio /sbin/ my_init bash
|
DockerホストのブラウザからNode.jsのポートを指定して確認します。
xip.ioとNginxのリバースプロキシをつかう
DockerコンテナのIPアドレスを確認します。
$ docker inspect b03feeae6063 | jq -r '.[0] | .NetworkSettings | .IPAddress' 172.17.0.207
|
Nginxの80だけをポートマップしてDockerコンテナを起動する。
$ docker run --rm -i -p 80:80 -t masato/xipio /sbin/ my_init bash
|
Dockerホストから、xip.ioを使ったURLを指定してブラウザで確認します。
まとめ
xip.ioを使ったURLで、Wildcard DNS
とHTTP Routing
の確認ができたので社内用のデータ分析環境はxip.ioで束ねて使ってみます。
特にクラスタ環境を構築するときはローカルで名前解決が必要な場合が多いので、xip.ioはとても便利な仕組みです。