mountハックはもういらない!
フォルダ構成
- project
- package.json
- package-lock.json
- index.js
- Dockerfile
Dockerfile
FROM node:slim
ENV PATH $PATH:/node_modules/.bin
COPY package.json package-lock.json ./
RUN npm install && npm cache clean --force
WORKDIR /usr/src/app
# Use -v ${HostOSWorkSpace}:/usr/src/app
CMD bash
説明
開発環境にcontainerを利用したい。
開発用containerは、普通のcontainerと違い、LocalWorkspaceディレクトリをマウントして使い、ソースコードの変更がHostOSにも反映されるようにしたい。
開発用containerは、npm runが動作できるようにしたい。
問題
node_modulesをdocker-build時にcontainerに含め、LocalWorkspaceに作らない運用をすると、docker-run時のmountで、containerのnode_modulesが隠れてしまう問題がある
従来の回避策A. node_modulesはcontaienrに含めない作戦
node_modulesをdocker-build時にcontainerに含めずに、docker-runでmountをしてから初めて作成し、HostOS上にnode_modulesを持ってくる。
だめな点
Windows上で動作しない。ファイルシステムやらパスやらの問題だと思われる。Windows上でマウントさせてはいけない。
従来の回避策B. mountハック
だめな点
- キモい
- docker-compose運用だと、upするたびに無限にvolumeが増えていく
- 毎回確実に
docker-compose down -v
しないといけない
- 毎回確実に
- HostOSに、空の node_modulesが作られる
- キモい。何かの表紙に空のnode_modulesがマウントされてしまうこともしばしば
今回の回避策
- node_modulesはcontainerに含める
- mountハックはしない
- node_modulesをmount dir以外に対比する
作戦
- そもそもこの仮想環境時代に、project-localなinstallなど不要(害悪)、global-installすればよいのでは
- 無理だった。npmはそういうちゃんと考えられた設計をしていない。npmライブラリも然り。
- package.jsonからglobal-installする機能がnpmに存在しない
- 依存解決の方法がglobalとlocalで違い、ライブラリがある
- localはflatでinstallされるが、globalはflatされない
- localをglobal-styleにはできるがその逆はできない
- 無理だった。npmはそういうちゃんと考えられた設計をしていない。npmライブラリも然り。
- project-localなinstall先をカレントディレクトリ以外に変更すればよいのでは
- できた
- nodeはNODE_PATHというものがありmoduleが見つからない場合順次そちらを確認しに行く
- mount dir以外の場所にnode_modulesをinstallしてNODE_PATHを通せばすべて解決では
- npm でカレントディレクトリ以外にnode_modulesを作る方法はない
- じゃあ作ってからmvする、もしくは、node_modulesを作りたいディレクトリにpackage.jsonを持ってくればよいのでは
- binにかんしては、NODE_PATHは面倒見てくれない
- PATHに追加すれば動いてくれるのでは?
Dockerfile
FROM node:slim
# はじめから /node_modules はNODE_PATHに通っているのでENV設定不要
ENV PATH $PATH:/node_modules/.bin # そのくせPATHは通っていないのでENV設定必要
# カレントディレクトリは / の想定
COPY package.json package-lock.json /
RUN npm install && npm cache clean --force # /node_modules を生成
# ここまでで依存パッケージがインストール済のコンテは完成
WORKDIR /usr/src/app
# Use -v ${HostOSWorkSpace}:/usr/src/app
CMD bash