Web アプリの開発環境を Docker で作っていたところ、nodemon がうまくファイル変更を検出してくれなくて困ったので、そのときのメモ。
マウントしたボリュームだと nodemon が watch してくれない問題
問題を再現するために、以下の3つのファイルを用意する。
ポイントとしては、ホストのディレクトリをコンテナ内にマウントしてそれをコンテナ内の nodemon が watch しているということ。
FROM node:12
ADD . /app
WORKDIR /app
CMD ["node", "."]
const http = require('http')
http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' })
res.end('ok')
}).listen(80)
version: '3'
services:
app:
build: .
ports:
- 8080:80
volumes:
- .:/app
command: npx nodemon
docker-compose up
でコンテナを起動し、Web ブラウザから http://localhost:8080/
にアクセスすると ok
と表示されるはず。
この開発用コンテナは nodemon から node プロセスを起動しているので、 index.js
が編集された場合には自動で restart してほしい。
しかしこの場合、いくら index.js
を編集しても nodemon はその変更を検出してくれない。
Chokidar が Polling するように設定する
nodemon はファイル監視のために内部で Chokidar を利用しており、そのドキュメントにはこのように書いてある。
usePolling (default: false). Whether to use fs.watchFile (backed by polling), or fs.watch. If polling leads to high CPU utilization, consider setting this to false. It is typically necessary to set this to true to successfully watch files over a network, and it may be necessary to successfully watch files in other non-standard situations. Setting to true explicitly on MacOS overrides the useFsEvents default. You may also set the CHOKIDAR_USEPOLLING env variable to true (1) or false (0) in order to override this option.
ネットワーク経由でファイルを監視する場合にはポーリングするように設定する必要があるらしい。
+ environment:
+ CHOKIDAR_USEPOLLING: 1
というわけで環境変数 CHOKIDAR_USEPOLLING=1
を設定した上で再試行したところ、無事にファイル変更を検出してくれるようになった。
めでたしめでたし。