Node.jsアプリのDockerイメージを作っているとpackage.jsonのnpm installのときにnode-gypによるネイティブモジュールのビルドが走ることがあります。Node.jsのコードやDockerfileの構成を変更するたびにビルドされて長いときは数分かかります。なにか良い方法がないかググっているとnpm package.json and docker (mounting it…)という記事を見つけました。このソリューションを使っていまビルドに時間がかかっているMeshbluのDockerイメージ作成を修正します。
Meshblu
IoTプラットフォームのMeshbluは内部でMQTTブローカーにMoscaを使い、LebelDBなどのネイティブモジュールのビルドに時間がかかります。またMeshbluのリポジトリのはDockerfileのままではビルドに失敗してしまいます。いくつか修正しながらnode_modulesを効率的にビルドできるようにしていきます。まずgit cloneしてデフォルトのディレクトリ状態を確認します。
$ cd ~/docker_apps |
Dockerイメージのビルド修正
アプリディレクトリの作成
デフォルトのリポジトリの状態だとDockerfileと同じ階層をそのまま/var/wwwにデプロイする形でイメージをビルドしています。server.jsなどのアプリケーションと、package.jsonをアプリディレクトリに移動します。このディレクトリでnpm installするのでnode_modulesが配置されます。
$ mkdir -p ./var/www |
Dockerfileにパッケージ追加
リポジトリからcloneした状態のDockerfileでビルドするとzmq.hとdns_sd.hがみつからないので失敗します。必要なパッケージをインストールします。
RUN apt-get install -y libzmq-dev libavahi-compat-libdnssd-dev |
Dockerfileのディレクトリ修正
node_modulesディレクトリやSupervisor設定ファイルの管理を別にして修正後にDockerイメージを再ビルドしなくてもdocker restartできるようにします。アプリや設定をnpmやインフラのパッケージのインストールを分離することができます。
node_modulesをアプリディレクトリの外の/dist/node_modulesに作成して、アプリディレクトリにはシムリンクを作る- Dockerfileの最後にCOPYコマンドで、アプリケーションを変更してもnpmインストールが起きないようにする
- Supervisorの設定ファイルはボリュームからアタッチするように変更する
... |
Meshbluの設定ファイルはDockerfile内でコメントアウトしたので、アプリディレクトリに移動します。
$ mv ./docker/config.js.docker ./var/www/config.js |
アプリディレクトリのボリューム
最後に/var/wwwのアプリディレクトリもDockerイメージから分離してボリュームでアタッチできるようにします。Dockerホストには/dist/node_modulesディレクトリは存在しませんが、コンテナ内では存在するシムリンクを作成します。
$ ln -s /dist/node_modules ./var/www/node_modules |
修正後のディレクトリ
Meshbluのリポジトリは以下のように修正しました。
$ tree -L 3 |
Dockerイメージのビルドと実行
Dockerイメージをビルドしてコンテナの起動を確認します。
$ docker build -t meshblu . |