Skip to content
intermediate Phase 7 · Docker in Development

Hot Reload & Live Sync

Enable hot reload with bind mounts and file watching in containers.

45m
0 problems
Topic Progress 0%

Hot Reload Fundamentals

Hot Reload Fundamentals

How Hot Reload Works in Docker

Host filesystem (bind mount)
    │
    ▼
Container watches /app/src for changes
    │
    ▼
File change detected → framework rebuilds → server reloads
    │
    ▼
Browser auto-refreshes

The key is bind mounting your source code into the container, then using the framework's built-in file watcher.

Node.js with Nodemon

FROM node:20
WORKDIR /app
COPY package*.json ./
RUN npm install -g nodemon
RUN npm install
COPY . .
EXPOSE 3000
CMD ["nodemon", "--watch", "src", "src/server.js"]
# docker-compose.dev.yml
services:
  api:
    build:
      context: .
      dockerfile: Dockerfile.dev
    volumes:
      - ./src:/app/src      # Bind mount source
      - /app/node_modules   # Keep container's node_modules
    ports:
      - "3000:3000"
    command: nodemon --watch src src/server.js

Python with uvicorn --reload

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--reload", "--host", "0.0.0.0"]
services:
  backend:
    volumes:
      - ./src:/app/src
    command: uvicorn main:app --reload --host 0.0.0.0

Go with Air

FROM golang:1.21
RUN go install github.com/air-verse/air@latest
WORKDIR /go/src/app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
CMD ["air"]
services:
  api:
    volumes:
      - ./src:/go/src/app
    command: air

Vue/React with Vite

services:
  frontend:
    build:
      context: ./frontend
    volumes:
      - ./frontend/src:/app/src
      - /app/node_modules
    ports:
      - "5173:5173"
    command: npm run dev -- --host

Vite uses WebSockets for HMR (Hot Module Replacement) — changes appear instantly without page reload.

Docker Compose Watch Mode

Docker Compose Watch Mode

Compose Watch (v2.22+) provides automatic file synchronization and container rebuilds.

Configure Watch

services:
  api:
    build:
      context: .
      dockerfile: Dockerfile
    develop:
      watch:
        # Sync file changes
        - action: sync
          path: ./src
          target: /app/src
        # Rebuild container on config change
        - action: rebuild
          path: ./package.json
        # Sync and exec command
        - action: sync+restart
          path: ./config
          target: /app/config

Usage

# Start watch mode
docker compose watch

# Start in background
docker compose watch &

# Watch outputs:
# [api] Syncing file changes to container...
# [api] Executing command: npm install
# [api] Container restarted

Watch Actions

Action Description
sync Copy changed files to container
rebuild Rebuild container from Dockerfile
sync+restart Sync files then restart container

Complete Example

services:
  frontend:
    build: ./frontend
    develop:
      watch:
        - action: sync
          path: ./frontend/src
          target: /app/src
        - action: sync+restart
          path: ./frontend/public
          target: /app/public

  api:
    build: ./api
    develop:
      watch:
        - action: sync
          path: ./api/src
          target: /app/src
        - action: rebuild
          path: ./api/package.json

Performance Tips

services:
  api:
    volumes:
      # Use cached consistency for macOS
      - ./src:/app/src:cached
      # Use delegated for write-heavy operations
      - ./dist:/app/dist:delegated
      # Named volume for node_modules (fast, no sync needed)
      - node_modules:/app/node_modules

volumes:
  node_modules:

File Sync Troubleshooting

File Sync Troubleshooting

Common Issues

1. Changes not detected:

# Check if volume is mounted correctly
docker inspect --format '{{json .Mounts}}' web | python3 -m json.tool

# Test file access inside container
docker exec web ls -la /app/src

# Check file modification time
stat ./src/server.js

2. File permission issues:

# macOS: Files created in container may have wrong UID
# Fix: Run container as host user
docker run --user $(id -u):$(id -g) myapp

# Linux: Files may be owned by root
# Fix: Change ownership on host
sudo chown -R $(id -u):$(id -g) ./src

3. macOS performance:

# Slow: Using bind mount through VM
v .:/app

# Faster: Named volume for heavy I/O
v node_modules:/app/node_modules
v .next:/app/.next

# Docker Desktop: Enable "Use VirtioFS" (Settings > General)
# Docker Desktop: Exclude large directories (Settings > Resources > File Sharing)

4. Inotify not working:

# Linux: Check inotify limits
cat /proc/sys/fs/inotify/max_user_watches
# Increase if needed
sudo sysctl fs.inotify.max_user_watches=524288

# Docker: inotify works for bind mounts but NOT for some volume types

5. Multiple watchers competing:

# Don't use both nodemon AND Docker watch
# Choose one:
# Option 1: Nodemon inside container
command: nodemon --watch src src/server.js

# Option 2: Docker Compose watch
# docker compose watch (handles sync and restart)

Debugging Steps

# 1. Verify mount exists
docker inspect web | grep -A 5 Mounts

# 2. Check container's view of files
docker exec web ls -la /app/src

# 3. Modify a file on host and check in container
touch ./src/test.txt
docker exec web ls -la /app/src/test.txt

# 4. Check file events
docker exec web inotifywait -m /app/src &
touch ./src/newfile.js
# Should see CREATE event

# 5. Check container logs for errors
docker logs web --tail 50