NestJS Docker HMR is not working
NestJS Docker HMR is not working
問題点
NestJSをDockerに載せて動かす時、HMRやlive reloadなどが動かない
解決策
まだわかっていない。
この件についてまるで分からないので分かる方教えて頂けると幸いです。
内容
Dockerfile
FROM node:20.12.0
RUN npm i -g @nestjs/cli
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
CMD [ "npm", "run", "docker:init" ]
docker-compose.yml
version: '3.8'
services:
api:
container_name: api
build: .
tty: true
ports:
- '3000:3000'
volumes:
- type: bind
source: .
target: /api
env_file:
- config/.env
depends_on:
mysql:
condition: service_healthy
mysql:
container_name: mysql
image: mysql:8
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --default-authentication-plugin=caching_sha2_password
ports:
- '3306:3306'
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: database
MYSQL_USER: user
MYSQL_PASSWORD: password
volumes:
- ./mysql_data:/var/lib/mysql
- ./mysql-init.sql:/docker-entrypoint-initdb.d/mysql-init.sql
healthcheck:
test: ['CMD', 'mysqladmin', 'ping', '-h', 'localhost']
interval: 10s
timeout: 5s
retries: 5
.dockerignore
node_modules
dist
mysql_data
package.json
"script": {
"docker:init": "npm run prisma:migrate && npm run prisma:generate && npm run start:dev"
]
試したこと
公式に記載されていること
- 必要パッケージのインストール
npm i --save-dev webpack-node-externals run-script-webpack-plugin webpack
-
webpack-hmr.config.js
の作成
const nodeExternals = require('webpack-node-externals');
const { RunScriptWebpackPlugin } = require('run-script-webpack-plugin');
module.exports = function (options, webpack) {
return {
...options,
entry: ['webpack/hot/poll?100', options.entry],
externals: [
nodeExternals({
allowlist: ['webpack/hot/poll?100'],
}),
],
plugins: [
...options.plugins,
new webpack.HotModuleReplacementPlugin(),
new webpack.WatchIgnorePlugin({
paths: [/\.js$/, /\.d\.ts$/],
}),
new RunScriptWebpackPlugin({ name: options.output.filename, autoRestart: false }),
],
};
};
をルートディレクトリに追加
-
package.json
に下記を追加
"start:dev": "nest build --webpack --webpackPath webpack-hmr.config.js --watch"
-
main.ts
の変更
module.hotの定義が無かった為、@types/webpack-env
をインストールした。
-> 無事、型定義エラーは消えた
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
// 下記追記
+ if (module.hot) {
+ module.hot.accept();
+ module.hot.dispose(() => app.close());
}
}
bootstrap();
この状態で、docker compose upして起動は確認できた。
webpack 5.90.1 compiled successfully in 1851 ms
その他試した事
webpack-hmr.config.js
上記のwebpack-hmr.config.js
を下記の様に変更した
const nodeExternals = require('webpack-node-externals');
const { RunScriptWebpackPlugin } = require('run-script-webpack-plugin');
module.exports = function (options, webpack) {
return {
...options,
entry: ['webpack/hot/poll?100', options.entry],
externals: [
nodeExternals({
allowlist: ['webpack/hot/poll?100'],
}),
],
plugins: [
...options.plugins,
new webpack.HotModuleReplacementPlugin(),
// WatchIgnorePluginは削除、または無視するパスを限定
new webpack.WatchIgnorePlugin({
- paths: [/\.js$/, /\.d\.ts$/],
+ paths: [/\.d\.ts$/], // .d.tsファイルのみ無視
}),
new RunScriptWebpackPlugin({
name: options.output.filename,
- autoRestart: false
+ autoRestart: true, // HMRで再起動するように設定
}),
],
};
};
docker-compose.yml
volumesの箇所を変更した
volumes:
- type: bind
source: .
target: /api
+ - /api/node_modules
volumes:
- type: bind
source: .
target: /api
+ - .:/app
+ - /api/node_modules
tsconfig.jsonの変更
以上のIssueから
+ "watchOptions": {
+ "watchFile": "fixedPollingInterval"
+ }
portチェック
await app.listen(3000)
ports:
- '3000:3000'
合っているから問題なさそう
推論
webpack-hmr.config.jsなどを導入し起動した際、
webpack 5.90.1 compiled successfully in 1851 ms
の表示と共にAPIリストなど出力されて起動は確認できた。
コードの変更検知->Docker変更認知
変更検知からDocker変更認知の辺りで上手くかみ合ってないと思っている。
何が正しいかもわかっていませんが…
tsc --watch
を入れて動かすとまた違うのか?
Dockerも詳しくないし、ここら辺の仕組みがまるで分からない。。。
React Vite on Dockerの環境では、HMRを動かすことに成功したが、NestJSはまるでわからん。
docker-compose.yml
に
volumes:
- type: bind
source: .
target: /api
+ - .:/app
+ - /api/node_modules
のような感じでvolumesにソースコードを渡してやったら出来たり、
export default defineConfig({
plugins: [react(), vanillaExtractPlugin()],
server: {
host: '0.0.0.0',
port: 3000,
hmr: true,
watch: {
usePolling: true,
},
},
})
と記載したら出来た。
host, portは問題ないはず
watch-pollingやhmrの起動辺りのオプションだったりがNestJSにもあると思われる。
Dockerに載せるようになってまるで分からない
Dockerへの理解がまるでないからきっとそこに原因はありそうな気がするけれど。。。
どなたか同様の問題で解決方法を知っていれば教えて頂けると幸いです。