将 dockerized Nginx 上的 React App 连接到 Express 服务器

ale*_*17k 5 nginx node.js docker reactjs

对于生产,我有一个Dockerfile使用 Nginx 提供 React 应用程序的服务:

# Stage 1

FROM node:15.6.0-alpine3.10 as react-build
WORKDIR /app/client/
COPY package*.json ./
RUN npm install
COPY ./ ./
RUN npm run build

# Stage 2 - the production environment

FROM nginx:1.19.6
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=react-build /app/client/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Run Code Online (Sandbox Code Playgroud)

对于用 Node / Express 编写的后端,我有以下内容Dockerfile

FROM node:15.6.0-alpine3.10
WORKDIR /app/server/
COPY package*.json ./
RUN npm install
COPY ./ ./
EXPOSE 8080
CMD ["npm", "start"]
Run Code Online (Sandbox Code Playgroud)

这些容器是这样管理的docker-compose.yml

version: "3.0"

services:
  # React Client
  web:
    image: xxx.dkr.ecr.eu-west-2.amazonaws.com/client:latest
    ports:
      - "80:80"

  # Node Server
  server:
    image: xxx.dkr.ecr.xxx.amazonaws.com/server:latest
    command: npm start
    ports:
      - "8080:8080"
Run Code Online (Sandbox Code Playgroud)

这里是nginx.conf

server {
  listen 80;
  
  location / {
    root /usr/share/nginx/html;
    index index.html index.htm;
    try_files $uri $uri/ /index.html =404;
  }
  
  include /etc/nginx/extra-conf.d/*.conf;
}
Run Code Online (Sandbox Code Playgroud)

前提

  • 在本地一切工作正常,我通过react-scripts和后端运行React docker-compose(因此没有React客户端)
  • 两张图片都已推送到,其内容与上面AWS ECR相同Dockerfile
  • 获取服务器时,端点看起来像fetch("/users/:id", {..})
  • package.json,我已经设置了"proxy": "http://localhost:8080/"
  • 两个镜像都已经过测试并且在开发和生产环境中都可以正常工作

问题

当从客户端访问 api 端点时,我得到一个405 (Not Allowed).

这实际上是预期的,因为我并没有真正告诉客户端(Nginx)将这些调用重定向到哪里。

检查网络选项卡,我可以看到请求是针对xxx.xxx.xxx.xxx:80(代表客户端)发出的,而它应该重定向到相同的地址但端口8080(Express 服务器所在的位置)。

在开发中它可以工作,因为proxy设置了 on package.json,但这仅用于开发,因此不会影响生产。

我尝试过的

  • 使用linkson docker-compose,不支持 fromAWS
  • 使用driver networkson docker-compose,不支持 fromAWS
  • proxy_pass正在添加nginx.conf,但未能使其正常工作

结论

因此,以所有这些为前提,当 Docker 化和生产时,如何将由 Nginx(客户端)提供的 React 构建连接到 Node 服务器?

我相信它应该需要一些配置nginx.conf,但我尝试的并没有让我走那么远。

预先感谢您的帮助!

Kon*_*rin 2

首先,您需要为您的 api 调用指定代理传递指令 - 我建议/api在您的 fetch 调用中添加。然后使用 docker-compose.yml 中指定的相同名称为后端服务提供上游。后端服务必须在 docker-compose.yml 中执行 Web 服务,这一点很重要,否则您将在 nginx 中收到如下连接错误nginx: [emerg] host not found in upstream "backend:8080"您可以按如下方式更新 nginx.conf:

upstream backend {
  server backend:8080;
}

server {
  listen 80;
  
  location / {
    root /usr/share/nginx/html;
    index index.html index.htm;
    try_files $uri $uri/ /index.html =404;
  }

  location /api {
    rewrite /api/(.*) /$1 break;
    proxy_pass http://backend;
  }
  
  include /etc/nginx/extra-conf.d/*.conf;
}
Run Code Online (Sandbox Code Playgroud)

或者只是在您的情况下提供到本地主机的代理传递,如下所示:

server {
   listen 80;
      
   location / {
     root /usr/share/nginx/html;
     index index.html index.htm;
     try_files $uri $uri/ /index.html =404;
   }
  
   location /api {
     rewrite /api/(.*) /$1 break;
     proxy_pass http://localhost:8080;
   }
      
   include /etc/nginx/extra-conf.d/*.conf;
}
Run Code Online (Sandbox Code Playgroud)