開発中のRESTクライアントはcurlコマンドを使っていましたが、他の人に使ってもらうためにコマンドラインツールが必要になります。サーバーと同じ開発言語のNode.jsで実装します。サーバーやデータベースのコンテナとセットにしてDocker Composeで配布する予定ですが、動作確認のためとりあえず単体で動くサンプルを作成しました。
プロジェクトの作成
プロジェクトのディレクトリを作成して以下のようなファイルを作成します。
$ cd ~/node_apps/iot-util
$ tree .
.
├── Dockerfile
├── app.js
├── commands
│ └── status.js
├── docker-compose.yml
├── node_modules -> /dist/node_modules
└── package.json
Dockerホストのプロジェクトのディレクトリに/dist/node_modules
へのシムリンクを作成します。
$ cd ~/node_apps/iot-util
$ ln -s /dist/node_modules .
Node.jsの実行はDockerコンテナで行いますが、イメージ再作成とnode_modulesの再ビルドを回避するためnode_modulesはDockerホストのボリュームにマウントして使います。ベースイメージはオフィシャルのnode:0.12を使います。
FROM node:0.12
MAINTAINER Masato Shimizu <ma6ato@gmail.com>
RUN mkdir -p /app
WORKDIR /app
COPY package.json /app/
RUN mkdir -p /dist/node_modules && ln -s /dist/node_modules /app/node_modules && \
npm install
COPY . /app
ENTRYPOINT ["npm", "start"]
Docker Composeを使ってビルドとCLIの実行をします。環境変数のMESHBLU_URL
は後でdocker-compose.ymlのlinksから取得します。
iotutil:
build: .
volumes:
- .:/app
environment:
- MESHBLU_URL=https://10.3.0.165/
Commander.jsを使う
Node.jsにはCLIを作るためのパッケージがいくつかありますが、よく使われているCommander.jsで実装していきます。
{
"name": "iot-util",
"description": "IoT Toolkit",
"version": "0.0.1",
"private": true,
"dependencies": {
"commander": "^2.8.1",
"request": "^2.55.0"
},
"scripts": {"start": "node app.js"}
}
以下のサイトを参考にしてエントリーポイントのapp.jsに必要なコードを書きます。
# !/usr/bin/env node
var program = require('commander')
, status = require('./commands/status.js');
program
.version('0.0.1')
.usage('<command>');
program
.command('status')
.description('show status')
.action(status.commandStatus);
program.parse(process.argv);
if (process.argv.length < 2) {
console.log('You must specify a command'.red);
program.help();
}
exports.program = program;
個別のコマンドはファイル名にコマンド名をつけて、commands
ディレクトリに配置します。今回はサンプルにstatus.jsを作成しました。サーバーは自己署名の証明書を使っています。Node.jsのrequestパッケージの場合はcurl --insecure
に相当するrejectUnauthorized: false
のオプションを付けます。
var request = require('request')
, path = require('path');
module.exports = {
commandStatus: function(symbol, command) {
var filename = path.basename(__filename),
cmd = filename.substr(0, filename.lastIndexOf('.'));
var options = {
url: process.env.MESHBLU_URL + cmd ,
agentOptions: {
rejectUnauthorized: false
}
}
request.get(options,function(error, response, body) {
if (!error && response.statusCode == 200){
var body = JSON.parse(body);
console.log(body);
} else if (error) {
console.log('Error: ' + error);
}
});
}
}
CLIの実行
Dockerイメージのビルドをします。
$ cd ~/node_apps/iot-util
$ docker-compose build
コマンドファイルと同じ名前の引数を渡してMeshbluのstatusを取得してみます。
$ docker-compose run --rm iotutil status
> iot-util@0.0.1 start /app
> node app.js "status"
{ meshblu: 'online' }
Removing iotutil_iotutil_run_1...
ヘルプを実行する場合は、--
に続けて--help
フラグを標準入力から取得します。
$ docker-compose run --rm iotutil -- --help
> iot-util@0.0.1 start /app
> node app.js "--help"
Usage: app <command>
Commands:
status show status
Options:
-h, --help output usage information
-V, --version output the version number
Removing iotutil_iotutil_run_1...