You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker-Compose部署Vue+Node.js Express跨域连接问题求助

编辑: 查看浏览器日志后发现:预检请求响应未通过跨域检查:'Access-Control-Allow-Origin'头的值为'http://127.0.0.1:8888',与请求源不匹配。

第二次编辑: 在帖子底部补充更多信息

Vue+Node+MariaDB Docker部署异常问题

本地运行正常,但Docker容器化部署后,提交数据无任何反应,API日志中无POST请求记录,推测UI与API间存在连接异常。技术栈包含Vue.js前端、Node.js Express后端/API、MariaDB数据库,参考教程搭建(仅修改了数据库名称和变量名)。Docker启动后,服务器已成功连接MariaDB,Vue应用可正常浏览,但提交数据时无响应。

文件夹结构

文件夹结构

核心配置文件

.env文件

MYSQLDB_USER=root
MYSQLDB_ROOT_PASSWORD=root
MYSQLDB_DATABASE=rgs
MYSQLDB_LOCAL_PORT=3307
MYSQLDB_DOCKER_PORT=3306

NODE_LOCAL_PORT=6868
NODE_DOCKER_PORT=8080

CLIENT_ORIGIN=http://127.0.0.1:8888
CLIENT_API_BASE_URL=http://127.0.0.1:6868/api/users

VUE_LOCAL_PORT=8888
VUE_DOCKER_PORT=80

compose.yaml文件

services:
    mariadb:
      image: mariadb
      restart: unless-stopped
      env_file: ./.env
      environment:
        - MYSQL_ROOT_PASSWORD=$MYSQLDB_ROOT_PASSWORD
        - MYSQL_DATABASE=$MYSQLDB_DATABASE
      ports:
        - $MYSQLDB_LOCAL_PORT:$MYSQLDB_DOCKER_PORT
      volumes:
        - db:/var/lib/mysql
      networks:
        - backend

    api:
      depends_on:
        - mariadb
      build: ./api
      restart: unless-stopped
      env_file: ./.env
      ports:
      - $NODE_LOCAL_PORT:$NODE_DOCKER_PORT
      environment:
        - DB_HOST=mariadb
        - DB_USER=$MYSQLDB_USER
        - DB_PASSWORD=$MYSQLDB_ROOT_PASSWORD
        - DB_NAME=$MYSQLDB_DATABASE
        - DB_PORT=$MYSQLDB_DOCKER_PORT
        - CLIENT_ORIGIN=$CLIENT_ORIGIN
      networks:
        - backend
        - frontend

    ui:
      depends_on:
        - api
      build:
        context: ./ui
        args:
          - VUE_APP_API_BASE_URL=$CLIENT_API_BASE_URL
      ports:
        - $VUE_LOCAL_PORT:$VUE_DOCKER_PORT
      networks:
        - frontend

volumes: 
  db:

networks:
  backend:
  frontend:

http-common.js文件

import axios from "axios";

export default axios.create({
  baseURL: process.env.VUE_APP_API_BASE_URL || "http://localhost:8080/api/users",
  headers: {
    "Content-type": "application/json"
  }
});

VUE UI Dockerfile

# Stage 1
FROM node:14 as build-stage

WORKDIR /ui
COPY package.json .
RUN npm install
COPY . .

ARG VUE_APP_API_BASE_URL
ENV VUE_APP_API_BASE_URL=$VUE_APP_API_BASE_URL

RUN npm run build

# Stage 2
FROM nginx:1.17.0-alpine

COPY --from=build-stage /ui/dist /usr/share/nginx/html
EXPOSE $VUE_DOCKER_PORT

CMD nginx -g 'daemon off;'

server Dockerfile

# syntax=docker/dockerfile:1

ARG NODE_VERSION=20.11.1

FROM node:${NODE_VERSION}-alpine

ENV NODE_ENV production

WORKDIR /api
COPY package.json . 
RUN npm install
COPY . .
CMD npm start

server.js文件

require("dotenv").config();
const express = require("express");
const cors = require("cors");

const app = express();

var corsOptions = {
  origin: process.env.CLIENT_ORIGIN || "http://localhost:8081"
};

app.use(cors(corsOptions));

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

const db = require("./app/models");
db.sequelize.sync()
  .then(() => {
    console.log("Synced db.");
  })
  .catch((err) => {
    console.log("Failed to sync db: " + err.message);
  });

// 开发环境专用代码(已注释)
/*db.sequelize.sync({ force: true }).then(() => {
  console.log("Drop and re-sync db.");
});*/

app.get("/", (req, res) => {
  res.json({ message: "Welcome to rgs." });
});

require("./app/routes/user.routes.js")(app);

const PORT = process.env.NODE_DOCKER_PORT || 8080;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}.`);
});

db.config.js文件

module.exports = {
  HOST: process.env.DB_HOST,
  USER: process.env.DB_USER,
  PASSWORD: process.env.DB_PASSWORD,
  DB: process.env.DB_NAME,
  port: process.env.DB_PORT,
  dialect: "mariadb",
  pool: {
    max: 5,
    min: 0,
    acquire: 30000,
    idle: 10000
  }
}; 

第二次编辑补充内容:
将CLIENT_ORIGIN=http://172.0.0.1:8888修改为CLIENT_ORIGIN=http://localhost:8888后,出现新问题:大部分页面可正常访问,但打开带输入框的页面时,触发资源未找到错误:

Failed to load resource: the server responded with a status of 404 (Not Found)
vue-router.mjs:3479 
ChunkLoadError: Loading chunk 578 failed.
(error: http://localhost:8888/js/578.1a9ac476.js)
    at t.f.j (app.6e12f49f.js:1:5420)
    at app.6e12f49f.js:1:2555
    at Array.reduce (<anonymous>)
    at t.e (app.6e12f49f.js:1:2520)
    at component (app.6e12f49f.js:1:391)
    at Ue (vue-router.mjs:2101:40)
    at vue-router.mjs:3309:22

相关代码片段

App.vue(部分)
<script setup>
import HeaderLogin from '@/components/AllSitesHeaderLogin.vue'
import HeaderLoggedIn from '@/components/AllSitesHeaderLoggedIn.vue'
...
</script>

<template>
  <!-- <div v-if="!loggedIn">  -->
  <div v-if="true"> 
    <HeaderLogin></HeaderLogin>
  </div>
AllSitesHeaderLogin.vue
<template>
  <header>
    <nav>
      <router-link to="/">Home</router-link> |
      <router-link to="/forum">Forum</router-link> |
      <router-link to="/add">Login</router-link> 
    </nav>
  </header>
</template>

<script>
export default {
  name: 'AllSitesHeaderLogin',
}
</script>
router.js
import { createWebHistory, createRouter } from "vue-router";

const routes = [
  { path: '/:pathMatch(.*)*', 
    component: () => import("./views/HomeView.vue") 
  },
  {
    path: "/",
    alias: "/home",
    name: "home",
    component: () => import("./views/HomeView.vue")
  },
  {
    path: "/login",
    name: "login",
    component: () => import("./views/LoginView.vue")
  },
  {
    path: "/add",
    name: "add",
    component: () => import("./views/RegisterView.vue")
  },
  {
    path: "/about",
    name: "about",
    component: () => import("./views/AboutView.vue")
  }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

export default router;

内容的提问来源于stack exchange,提问作者hellodarkness

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 10:57:09