如何通过 Nginx 反向代理为 Vite 开发服务器提供服务

Nad*_*oui 2 nginx reactjs monorepo vite turborepo

我正在开发一个包含多个微服务(、、 )的Typescript monorepo。每个微服务都有自己的服务。为了使开发体验更加流畅,我们决定添加一台服务器(在图像中),该服务器将收集每个微服务的所有端口并将它们全部保留在一个.turboreponextjsexpressjscreate-react-appPORTNginxdockerPORT

当我尝试添加 aVite react app并将其放在同一个 Nginx 服务器后面时,它不起作用,因为它正在尝试访问本地计算机中的 node_modules 中的文件。

有人有解决方法吗?

以下是我的配置示例:

Nginx 配置文件:

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;

}
Run Code Online (Sandbox Code Playgroud)

我的 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()],
  };
});
Run Code Online (Sandbox Code Playgroud)

Nginx 的错误:

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" "-"
Run Code Online (Sandbox Code Playgroud)

11t*_*ion 5

我假设您已将 Nginx 的容器端口暴露80给 docker 主机端口3000,这就是代理请求出现的原因localhost:3000。因此请求是localhost:3000代理请求。

最有可能的是您的配置文件尚未被 Nginx 获取,这就是为什么它没有检测到反向代理配置并尝试从其静态内容目录中读取该文件。

如果它检测到代理配置并且由于某种原因目标应用程序已关闭或无法访问,您将看到502如下错误而不是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" "-"
Run Code Online (Sandbox Code Playgroud)

您可以通过在杀死您的 React 应用程序后访问代理 URL 来测试这一点,如果 Nginx 仍然记录 404 而不是 502,则它尚未检测到代理设置。

此外,位置上下文路径必须以正斜杠结尾才能工作,如下所示

location /foo/ {
    proxy_pass http://Lan-IP-Of-Docker-Host:8080/;
}
Run Code Online (Sandbox Code Playgroud)

另外,我不确定host.docker.internal设置了什么,如果您在本地主机上运行容器,则检查您的主机文件是否有由 docker 创建的条目用于host.docker.internal映射到127.0.0.1

Windows 10 主机文件:C:\Windows\System32\drivers\etc\hosts

Linux 主机文件:/etc/hosts

如果设置为127.0.0.1,则代理将无法正确转发请求,因为它将解析为容器本身内部的环回地址。您可以通过将host.docker.internal主机名替换为 Docker 主机的 LAN IP 地址来初步测试此配置。对我来说,这是我的本地 LAN 地址,例如10.0.1.x

最后,我Dockerfile为 Nginx 创建了一个简单的代理,并通过修改文件来测试代理default.conf,请参阅下面的代码。尝试使用此配置运行代理以查看是否有效

多克菲

FROM nginx:1.23.4

COPY default.conf /etc/nginx/conf.d/default.conf
Run Code Online (Sandbox Code Playgroud)

默认配置文件

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;
    #}
}
Run Code Online (Sandbox Code Playgroud)

Docker 构建、运行和停止命令

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
Run Code Online (Sandbox Code Playgroud)