Edited at

node_modulesを隔離したい

どうも。諸々の事情で関西の某地域のバス[お察しください]になった者です。


問題

Dockerは最早聞き慣れた言葉になっていると思います。そして、NodeJSやこれを使うフロントエンドと連携する時、こんなコードを書くと思います。


docker-compose.yml

version: "3"

services:
db:
image: mongo:latest
restart: unless-stopped
environment:
MONGO_INITDB_ROOT_USERNAME: prj
MONGO_INITDB_ROOT_PASSWORD: prj
ports:
- 27017:27017
volumes:
- ./data/db:/data/db
backend:
build: ./backend
stop_signal: SIGINT
ports:
- 8080:8080
volumes:
- .:/opt/code
depends_on:
- db
environment:
DEVEL: 'true'
CONFIG_NAME: devel.conf
frontend: # ここにNodeJSが使われている
build: ./frontend
stop_signal: SIGINT
ports:
- 4200:4200
volumes:
- ./frontend:/code
depends_on:
- backend

で、実行するとコンテナが色々準備してくれる・・・と。ですが、これだと、ホスト側のnode_modulesディレクトリとコンテナ側のnode_modulesが共有される事になります。オマケに、環境にもよりますが、少なくともLinux上でコードを書いているオタクな人の環境だと、package.jsonpackage-lock.jsonの所有権が別の誰かになってしまう事もあります。これだとどうもやりにくい。なので、せめてnode_modulesだけはホスト側とコンテナ側で別々にしておきたい。

そんな方法あるの? はいありました。


/code/node_modulesにVolumeを割り当てる

Dockerのボリュームというのは、外部のストレージ、つまりホスト側のどこかしらのディレクトリからマウントしたり、コンテナとは別のストレージにデータを保存したい場合なんかに用いられていますが、実は、VolumeによってマウントされたディレクトリのサブディレクトリにVolumeをマウントしても良いんです。つまり、さっきのdocker-compose.ymlを次のように書き換えます。


docker-compose.yml

version: "3"

services:
db:
image: mongo:latest
restart: unless-stopped
environment:
MONGO_INITDB_ROOT_USERNAME: prj
MONGO_INITDB_ROOT_PASSWORD: prj
ports:
- 27017:27017
volumes:
- ./data/db:/data/db
backend:
build: ./backend
stop_signal: SIGINT
ports:
- 8080:8080
volumes:
- .:/opt/code
depends_on:
- db
environment:
DEVEL: 'true'
CONFIG_NAME: devel.conf
frontend:
build: ./frontend
stop_signal: SIGINT
ports:
- 4200:4200
volumes:
- ./frontend:/code
- /code/node_modules # ここに注目!!
depends_on:
- backend

こうすることによって、node_modulesを削除する時にroot権限を使う必要がなくなり、ホスト側でNodeJSのコマンド、ng updateなんかを実行することができます❤

めでたしめでたし


参考記事