node_modulesの取り扱いには注意が必要
Dockerを利用して環境構築をする際にはnode_modulesの取り扱いに注意する必要があります。
何も意識していないとホスト側でyarn installなどをしてしまうとエラーが発生することがあります。
またyarn installなどをDockerfileで実行した際にnode_modulesが削除されたりします。
以下の記事ではコンテナ内のnode_modulesが消える問題の改善方法について記載しています。
しかし、上記の記事に記載している方法ではホスト側のnode_modulesが空になってしまいます。
今回は、ホスト側のnode_modulesが空になる問題の改善方法について記載します。
Next.jsの環境で試したのでNext.jsで記載しますが他でも応用可能と思います。
ホスト側のnode_modulesが空になる原因と改善方法
原因
docker-compose.ymlを以下のようにすることでnode_modulesに対してボリュームを設定してバインドマウントから除外しています。
バインドマウントから除外することでコンテナ内のnode_modulesが消えることは回避できますが、 node_modulesがボリュームで管理されるようになるため、ホスト側には反映されなくなります。
そのため、ボリュームで管理されているnode_modulesのみ空となってしまいます。
version: '3.9'
services:
front:
build: .
volumes:
- .:/myapp
- node_modules:/myapp/node_modules
environment:
NODE_ENV: development
ports:
- 3000:3000
volumes:
node_modules:
バインドマウントやボリュームの違いなどについては以下の記事をご参照ください。
改善方法
以下で紹介する方法はWindowsでは動作しないようです。
docker-compose.ymlを以下のようにすることでボリュームで管理されているnode_modulesの内容をホスト側にも表示できます。
version: '3.9'
services:
front:
build: .
volumes:
- .:/myapp
- node_modules:/myapp/node_modules
environment:
NODE_ENV: development
ports:
- 3000:3000
volumes:
node_modules:
driver: local
driver_opts:
type: none
device: ${PWD}/node_modules
o: bind
下のvolumes内のdeviceには絶対パスを記述する必要があります。
これで、docker compose upするとホスト側にもnode_modulesの中身が表示されます。
$ docker compose up
[+] Running 3/3
⠿ Network next_default C... 0.0s
⠿ Volume "next_node_modules" Created 0.0s
⠿ Container next-front-1 Created 93.0s
Attaching to next-front-1
next-front-1 | yarn run v1.22.18
next-front-1 | $ next dev
next-front-1 | ready - started server on 0.0.0.0:3000, url: http://localhost:3000
next-front-1 | wait - compiling...
next-front-1 | event - compiled client and server successfully in 2.2s (124 modules)
上のContainer next-front-1 Created 93.0sを見てわかるとおり、ボリュームが作成された後、初回のdocker compose upに時間がかかります。
また注意点としては、ホスト側に空のnode_modulesを用意する必要があります。
用意していないと以下のようなエラーが出ます。
Error response from daemon: error while mounting volume
'/var/lib/docker/volumes/next_node_modules/_data': failed to mount local volume:
mount /Users/user_name/Documents/sources/docker-next-test/Next/node_modules:
/var/lib/docker/volumes/next_node_modules/_data, flags: 0x1000:
no such file or directory
空の node_modules を用意してもエラーが出る場合
空のnode_modulesを用意してdocker compose buildしたにもかかわらず以下のようなエラーが出ることがあります。
$ docker compose build
$ docker compose up
[+] Running 3/0
⠿ Network next_default C... 0.0s
⠿ Volume "next_node_modules" Created 0.0s
⠿ Container next-front-1 Created 0.0s
Attaching to next-front-1
next-front-1 | yarn run v1.22.18
next-front-1 | $ next dev
next-front-1 | /bin/sh: 1: next: not found
next-front-1 | info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
next-front-1 | error Command failed with exit code 127.
コンテナ内で以下のコマンドを実行し、node_modulesが本当に空か確認します。
myuser@36f641e85791:/myapp$ ls -a node_modules
. .. .DS_Store
ホスト側のnode_modulesに.DS_Storeがあれば、これがコンテナ側に反映されてしまうことが原因です。
ホスト側のnode_modules内の.DS_Storeを削除するために以下を実行します。
$ rm node_modules/.DS_Store
そしてdocker compose down -v → docker compose upで改善します。
なお上記の他にホスト側でもyarn installすることや(ホスト側が空になる状態であればホスト側の変更はコンテナ内に反映されません)、VSCodeで Remote - Containersを利用することでも対処できます。
Remote - Containersの使用方法については以下をご参照ください。
またホスト側にnode_modulesの中身が表示されるようになりましたが、ホスト側の変更がコンテナ内に反映されてしまいます。
ホスト側でyarn installなどをするとエラーの原因となることがあります。
ホスト側でのyarn install等を禁止する方法については以下のページをご参照ください。