Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to serve Vite development server behind an Nginx reverse proxy

I'm working on a Typescript monorepo using turborepo that holds multiple microservices (nextjs, expressjs, create-react-app). each of these microservices is served in its own PORT. In order to make the development experience more fluid, we decided to add a Nginx server (in a docker image) that will collect all the ports from each Microservice and reserve them all under one PORT.

When I tried to add a Vite react app and put it behind the same Nginx server, it didn't work because it is trying to access the files in node_modules in my local machine.

Does anyone have a workaround?

Below is a sample of my configs:

Nginx config file :

upstream imgproxy {
    server imgproxy:3000;
}


server {
    listen 80;

    location / {
        return 301 https://$host:3000$request_uri;
    }
}


server {
    listen 443 ssl;
    client_max_body_size 240M;
    ssl_certificate    cert/localhost3000.crt;
    ssl_certificate_key    cert/localhost3000.key;

    location /api/v1/auth {
          proxy_pass http://host.docker.internal:4001;
    }

    location /dashboard {
          proxy_pass https://host.docker.internal:3001;
    }

    location /api/v1/blogs {
          proxy_pass http://host.docker.internal:4010;
    }

    location / {
          proxy_pass http://host.docker.internal:4200;
    }

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    include h5bp/tls/policy_balanced.conf;
    # Custom error pages
    include h5bp/errors/custom_errors.conf;

    # Include the basic h5bp config set
    include h5bp/basic.conf;

}

My vite.conf.ts

import { defineConfig, loadEnv } from "vite";
import react from "@vitejs/plugin-react-swc";
import fs from "fs";
import tsconfigPaths from "vite-tsconfig-paths";
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
  return {
    base: "/dashboard",
    server: {
      port: 3001,
      https: {
        cert: fs.readFileSync("../../nginx/cert/localhost3000.crt"),
        key: fs.readFileSync("../../nginx/cert/localhost3000.key"),
      },
    },
    plugins: [react(), tsconfigPaths()],
  };
});

Nginx's errors :

2023/05/05 13:54:02 [error] 33#33: *2 open() "/etc/nginx/html/dashboard/node_modules/.vite/deps/react_jsx-dev-runtime.js" failed (2: No such file or directory), client: 172.20.0.1, server: , request: "GET /dashboard/node_modules/.vite/deps/react_jsx-dev-runtime.js?v=12d55949 HTTP/1.1", host: "localhost:3000", referrer: "https://localhost:3000/dashboard/src/index.tsx"
172.20.0.1 - - [05/May/2023:13:54:02 +0000] "GET /dashboard/node_modules/.vite/deps/react_jsx-dev-runtime.js?v=12d55949 HTTP/1.1" 404 178 "https://localhost:3000/dashboard/src/index.tsx" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36" "-"
172.20.0.1 - - [05/May/2023:13:54:02 +0000] "GET /dashboard/@react-refresh HTTP/1.1" 200 3393 "https://localhost:3000/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36" "-"
2023/05/05 13:54:03 [error] 33#33: *2 open() "/etc/nginx/html/dashboard/node_modules/.vite/deps/react.js" failed (2: No such file or directory), client: 172.20.0.1, server: , request: "GET /dashboard/node_modules/.vite/deps/react.js?v=12d55949 HTTP/1.1", host: "localhost:3000", referrer: "https://localhost:3000/dashboard/src/index.tsx"
172.20.0.1 - - [05/May/2023:13:54:03 +0000] "GET /dashboard/node_modules/.vite/deps/react.js?v=12d55949 HTTP/1.1" 404 178 "https://localhost:3000/dashboard/src/index.tsx" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36" "-"
2023/05/05 13:54:03 [error] 35#35: *6 open() "/etc/nginx/html/dashboard/node_modules/.vite/deps/react-redux.js" failed (2: No such file or directory), client: 172.20.0.1, server: , request: "GET /dashboard/node_modules/.vite/deps/react-redux.js?v=12d55949 HTTP/1.1", host: "localhost:3000", referrer: "https://localhost:3000/dashboard/src/index.tsx"
172.20.0.1 - - [05/May/2023:13:54:03 +0000] "GET /dashboard/node_modules/.vite/deps/react-redux.js?v=12d55949 HTTP/1.1" 404 178 "https://localhost:3000/dashboard/src/index.tsx" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36" "-"
172.20.0.1 - - [05/May/2023:13:54:03 +0000] "GET /dashboard/@fs/C:/Users/nader/Documents/devProjects/boilerplate/packages/browser/core-ui/DarkModeProvider/index.tsx HTTP/1.1" 200 2026 "https://localhost:3000/dashboard/src/index.tsx" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36" "-"
like image 500
Nader Zouaoui Avatar asked Oct 31 '25 00:10

Nader Zouaoui


1 Answers

I'm assuming you have expose Nginx's container port 80 to docker host port 3000, that's why requests to proxy are coming at localhost:3000.Thus request to localhost:3000 are proxied requests.

Most likely your configuration file has not been picked up by the Nginx, that's why it doesn't detect the reverse proxy configuration and tries to read the file from it's static content directory.

If it had detected proxy configuration and for some reason target application is down or cannot be reached, you'll see 502 error like below instead of 404

172.17.0.1 - - [13/May/2023:19:43:13 +0000] "GET /foo/hello HTTP/1.1" 502 497 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36" "-"

You can test this by accessing the proxy URL after killing your react app, if Nginx still logs 404 instead of 502, it hasn't detected the proxy settings.

Also, location context path must end with a forward slash to work, like below

location /foo/ {
    proxy_pass http://Lan-IP-Of-Docker-Host:8080/;
}

Also, I'm not sure what host.docker.internal is set to, if you're running container on localhost then check if your hosts file has an entry made by docker for host.docker.internal mapped to 127.0.0.1

Windows 10 hosts file: C:\Windows\System32\drivers\etc\hosts

Linux hosts file: /etc/hosts

If it's set to 127.0.0.1, then proxy will not forward request correctly, as it will resolve to the loopback address inside the container itself. You can initially test this configuration by replacing host.docker.internal hostname with LAN IP address of Docker host. For me it's my local LAN address like 10.0.1.x

Finally, I created a simple Dockerfile for Nginx and test the proxy by modifying default.conf file, see the code below. Try running proxy with this configuration to see if this works

Dockerfie

FROM nginx:1.23.4

COPY default.conf /etc/nginx/conf.d/default.conf

default.conf

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #access_log  /var/log/nginx/host.access.log  main;

# REVERSE PROXY SETTING, Context path ends with forward slash
    location /foo/ {
        proxy_pass http://Lan-IP-Of-Docker-Host:8080/;
    }

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

Docker build, run and stop commands

docker build -t test-nginx ./

//Container will be removed after its stopped because of --rm
docker run --rm --name test-nginx -p 3000:80 test-nginx

//Stops immediately
docker stop test-nginx -t 0
like image 127
11thdimension Avatar answered Nov 02 '25 00:11

11thdimension