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 . |