Hot reload doesn't work in a vite+vue3 dockerized app

36 views Asked by At

I have a vite+vue3 project that I'm trying to dockerize it. When I run docker-compose up -d everything is right, except hot reloading after a change. What is the problem?

vite.config.ts:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from "path"

import tailwind from "tailwindcss"
import autoprefixer from "autoprefixer"

export default defineConfig({
  css: {
    postcss: {
      plugins: [tailwind(), autoprefixer()],
    },
  },
  plugins: [vue()],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  }
})

Dockerfile:

FROM node:16-alpine as builder
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx:alpine as production-build
COPY nginx.conf /etc/nginx/nginx.conf

RUN rm -rf /usr/share/nginx/html/*

COPY --from=builder /dist /usr/share/nginx/html
EXPOSE 7040
ENTRYPOINT ["nginx", "-g", "daemon off;"]

docker-compose.yml:

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "7040:7040"
1

There are 1 answers

0
datawookie On

If you want to have hot reloading then you have (at least!!) two options.

Assume that the project layout looks something like this:

├── app
│   ├── Dockerfile
│   ├── index.html
│   ├── package.json
│   ├── package-lock.json
│   ├── public
│   │   └── vite.svg
│   ├── README.md
│   ├── src
│   │   ├── App.vue
│   │   ├── assets
│   │   │   └── vue.svg
│   │   ├── components
│   │   │   └── HelloWorld.vue
│   │   ├── main.js
│   │   └── style.css
│   └── vite.config.js
├── docker-compose.yml
├── layout.txt
└── nginx.conf

In both cases this is what app/Dockerfile looks like:

FROM node:16

WORKDIR /app

COPY package*.json ./
RUN npm install

CMD ["npm", "run", "dev"]

Since you are wanting hot reloading the Docker container will be running a development server.

Option 1:

services:
  web:
    build:
      context: app
    ports:
      - "3000:5173"
    volumes:
      - ./app:/app

This will simply build and run the container, mapping container port 5173 to port 3000 on the host. Open http://127.0.0.1:3000/ in your browser. This will give you true hot reload in the sense that modifications to the code will immediately reflect in the browser.

Option 2

If you want to layer NGINX on top of that (probably not necessary for a development setup?):

services:
  web:
    build:
      context: app
    volumes:
      - ./app:/app

  nginx:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - web

With the following nginx.conf:

server {
    listen 80;

    location / {
        proxy_pass http://web:5173;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

This will serve the site at http://127.0.0.1/. You need NGINX to also relay the Web Socket connection to the app to ensure that the browser is automatically refreshed when content changes.

enter image description here