Why NestJS Hot Reload Does Not Work in Docker and How to Fix It Properly

Published: (December 22, 2025 at 04:51 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

The core misunderstanding

Docker does not watch your files. It only sees what exists inside the container. Whether changes are reflected depends entirely on:

  1. How files get into the container
  2. How NestJS is started
  3. Whether filesystem events propagate correctly

Mixing development‑mode expectations with production‑mode setups will prevent hot reload from working.

How NestJS hot reload works without Docker

When you run NestJS locally with:

npm run start:dev

the Nest CLI uses a file watcher. On file change the process restarts automatically.

  • No Webpack involved.
  • No HMR (Hot Module Replacement).
  • Just a process restart, powered by native filesystem events.

What changes when you introduce Docker

Inside a container, file watching depends on three things:

  1. File injection – are you mounting the source code or copying a snapshot?
  2. Startup command – are you running Nest in watch mode?
  3. Event propagation – do filesystem events reach the container?

If any of these is mis‑configured, hot reload breaks.

The only setup that works reliably for development

All of the following must be true:

  1. Source code is mounted via a volume
  2. NestJS runs in watch mode (start:dev)
  3. File watching works inside Docker

Volumes are non‑negotiable

A Dockerfile that simply copies the code:

COPY . .

creates a static snapshot—perfect for production, but useless for development because Docker never sees local edits.

Instead, use a docker‑compose.yml (or docker run) that mounts the project directory:

services:
  app:
    build: .
    volumes:
      - .:/usr/src/app
      - /usr/src/app/node_modules   # exclude host node_modules

The line .:/usr/src/app is the backbone of hot reload.

Excluding node_modules

Mounting the host’s node_modules can cause native‑module mismatches. Excluding it (as shown above) ensures the container uses its own dependencies.

Run Nest in watch mode

npm run start:dev   # ✅ correct
# ❌ wrong alternatives:
node dist/main.js
nest start

Running compiled JavaScript disables the watcher, so hot reload is impossible.

The macOS and Windows file‑watching problem

Docker Desktop runs Linux containers inside a VM. Native filesystem events often do not propagate from macOS/Windows hosts into the container, causing NestJS to miss changes.

Fix: enable polling

Set the following environment variables so Node‑based watchers poll for changes instead of relying on events:

CHOKIDAR_USEPOLLING=true
WATCHPACK_POLLING=true

Add them to your docker‑compose.yml (or Dockerfile) under environment:. Polling is a well‑known, reliable workaround.

The webpack confusion explained

NestJS supports two reload strategies:

  1. Process restart – the default Nest CLI watcher (used with start:dev).
  2. Hot Module Replacement (HMR) – requires Webpack.

Webpack is only needed if you deliberately enable HMR. Indicators that HMR is active:

// main.ts
if (module.hot) {
  module.hot.accept();
}
// nest-cli.json
{
  "compilerOptions": { ... },
  "webpack": true   // <-- enables HMR
}

If you never intended HMR, you don’t need Webpack at all. Installing it just to “fix” Docker reload issues is usually a red‑herring; the missing piece is often the polling configuration described above.

When Webpack HMR makes sense

  • Your application has a long startup time.
  • You want instant reload without restarting the Node process.
  • You have explicitly enabled HMR in the Nest config.

For most backend APIs, a simple process restart on file change is sufficient and far less complex.

Development vs. production mental model

AspectDevelopmentProduction
VolumesUse host‑to‑container mountsNo volumes; copy files during build
Start commandnpm run start:dev (watch mode)Run compiled JS (node dist/main.js)
File watchingEnable polling if on macOS/WindowsNot needed
RebuildsNever rebuild the image for code changesRebuild image on each change
WebpackOptional, only for HMRNot required

Mixing these worlds (e.g., using volumes in production or rebuilding images for every change) leads to broken workflows.

Final thoughts

  • Docker isn’t broken.
  • NestJS isn’t broken.
  • Hot reload isn’t magic; it’s just file‑watching.

Understanding how files enter the container and how NestJS watches them makes the behavior predictable. If you find yourself rebuilding Docker images just to see a console‑log update, revisit the volume, start‑command, and polling settings. And if you installed Webpack solely to make file watching work, you probably didn’t need it.

If this article saved you time, it will likely save someone else hours of frustration too.

Back to Blog

Related posts

Read more »

PSX: The Project Structure Checker

PSX – Project Structure eXtractor A command‑line tool that validates your project layout and fixes it automatically. Think of it as a linter for the whole repo...