docker - 如果使用 docker 部署,为什么 MERN 应用程序无法与后端通信?

标签 docker docker-compose deployment proxy digital-ocean

我使用 Docker 将 MERN 应用程序部署到 digital ocean 水滴。如果我在我的 PC 上本地运行 docker-compose.yml 文件,它运行良好。我有 2 个容器:1 个后端,1 个前端。如果我尝试在 Droplet 上进行组合,前端似乎没问题,但无法与后端通信。

enter image description here

我使用 http-proxy-middleware,我的 setupProxy.js 文件:

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function (app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: 'http://0.0.0.0:5001',
      changeOrigin: true,
    })
  );
};

我试过 target: 'http://main-be:5001', 也是,因为 main-be 是我的后端容器的名称,但得到相同的错误。只是请求 URL 在 chrome 中是 http://main-be:5001/api/auth/login/devops/网络

enter image description here

...还有另一页: enter image description here

我的 docker-compose.yml 文件:

version: '3.4'

networks:
  main:

services:
  main-be:
    image: main-be:latest
    container_name: main-be
    ports:
      - '5001:5001'
    networks:
      main:
    volumes:
      - ./backend/config.env:/app/config.env
    command: 'npm run prod'
  main-fe:
    image: main-fe:latest
    container_name: main-fe
    networks:
      main:
    volumes:
      - ./frontend/.env:/app/.env
    ports:
      - '3000:3000'
    command: 'npm start'

frontend 文件夹中的Dockerfile:

FROM node:12.2.0-alpine
COPY . .
RUN npm ci
CMD ["npm", "start"]

backend 文件夹中的Dockerfile:

FROM node:12-alpine3.14
WORKDIR /app
COPY . .
RUN npm ci --production
CMD ["npm", "run", "prod"]

backend/package.json 文件:

  "scripts": {
    "start": "nodemon --watch --exec node --experimental-modules server.js",
    "dev": "nodemon server.js",
    "prod": "node server.js"
  },

前端/.env 文件:

SKIP_PREFLIGHT_CHECK=true
HOST=0.0.0.0

backend/config.env 文件:

DE_ENV=development
PORT=5001

我的 deploy.sh 脚本构建图像,复制到 Droplet...

#build and save backend and frontend images
docker build -t main-be ./backend & docker build -t main-fe ./frontend
docker save -o ./main-be.tar main-be & docker save -o ./main-fe.tar main-fe

#deploy services
ssh root@46.111.119.161 "pwd && mkdir -p ~/apps/first && cd ~/apps/first && ls -al && echo 'im in' && rm main-be.tar && rm main-fe.tar &> /dev/null" 

#::scp file
#scp ./frontend/.env root@46.111.119.161:~/apps/first/frontend

#upload main-be.tar and main-fe.tar to VM via ssh
scp ./main-be.tar ./main-fe.tar root@46.111.119.161:~/apps/thesis/

scp ./docker-compose.yml root@46.111.119.161:~/apps/first/
ssh root@46.111.119.161 "cd ~/apps/first && ls -1 *.tar | xargs --no-run-if-empty -L 1 docker load -i"

ssh root@46.111.119.161 "cd ~/apps/first && sudo docker-compose up"

前端/src/utils/axios.js:

import axios from 'axios';

export const baseURL = 'http://localhost:5001';

export default axios.create({ baseURL });

frontend/src/utils/constants.js:

const API_BASE_ORIGIN = `http://localhost:5001`;

export { API_BASE_ORIGIN };

我已经尝试了好几天,但看不出问题出在哪里,非常感谢任何帮助。

最佳答案

我不是 MERN 方面的专家(我们主要运行 Angular 和 .Net),但我必须警告您一件事。我们在一开始设置它时遇到了一个问题,它在容器中本地工作,但在我们的部署服务器上却不行,因为我们忘记了有关 Web 应用程序的基本知识。

应用程序在您的浏览器中运行,而如果您在其他地方部署应用程序堆栈,服务的 REST(API、数据库等)则不会。所以在你的应用程序中引用你的 IP/DNS/localhost 是行不通的,因为那里什么都没有。包含 WEB 应用程序的容器仅服务于您的浏览器(客户端)文件,然后 JS 和逻辑在您的浏览器中执行,而不是在容器中执行。

我怀疑这可能会影响您连接到后端的能力。

要解决这个问题,您有两个选择。

  • 创建一个 HTTP 代理作为附加服务,然后您的 FE 调用该代理(设置域和路由),例如 Nginx、Traefik 等,然后该代理可以使用服务名称引用您的后端,因为它确实与 API 存在于相同的环境中。
  • 直接从容器公开 HTTP 端口,然后您的 FE 可以调用 remoteServerIP:exposedPort,您将直接连接到容器的接口(interface)。 (注意:我不推荐这种方式用于实际使用,仅用于测试不使用任何代理的直接连接)

关于docker - 如果使用 docker 部署,为什么 MERN 应用程序无法与后端通信?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71952390/

相关文章:

asp.net-mvc - FTP部署asp.net mvc站点的最佳方法是什么?

node.js - "Error: spawn mongoexport ENOENT"运行 dockerized Node 应用程序时

在 Docker 上安装 Wordpress。试图跳过安装页面

mysql - 如何通过 SSH 连接到 MySQL Docker 容器?

docker - 将目录路径添加到Docker镜像

Docker secret 不适用于 MYSQL_ROOT_PASSWORD_FILE

c# - "Manifest XML signature is not valid"

java - 开发和生产的属性

docker - 如何停止Docker容器,以便使用相同命令重新运行?

docker - 如何在运行 docker-compose up 时运行多个 docker 容器(gitlab-ci)