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

Docker Compose中JavaScript客户端无法调用Node.js API问题

解决Docker Compose中JS前端无法调用Node.js API的问题

问题根源

核心问题是运行环境的网络差异:

  • PHP前端代码在Apache容器内部执行,属于Docker Compose创建的内部网络,因此可以直接通过服务名api访问后端API,不存在跨域和域名解析问题。
  • JS前端代码在用户的浏览器中执行,浏览器处于宿主机的网络环境,而非Docker内部网络:
    1. 无法解析Docker内部的服务名api,容器IP属于Docker网桥的私有IP,仅宿主机和其他容器能访问,浏览器无法直接连通。
    2. 即使能连通,使用mode: 'no-cors'会导致浏览器限制读取响应内容,因为该模式仅允许无跨域风险的请求头和响应,无法获取JSON数据。

解决方案一:直接访问宿主机映射端口 + 配置CORS

步骤1:给Node.js API添加CORS支持

浏览器发起跨域请求需要后端允许,给API安装并启用CORS中间件:

  1. 在API目录执行:
npm install cors
  1. 修改API的index.js,引入并使用cors:
const express = require('express');
const cors = require('cors');
const app = express();

// 允许所有前端域名访问(生产环境建议指定具体域名,比如http://localhost:5002)
app.use(cors());

app.get('/', (req, res) => {
  res.json({
    "products": [
      "icecream",
      "milk",
      "fries",
      "cheese",
      "oranges",
      "bananas"
    ]
  });
});

app.listen(3000, () => {
  console.log('API running on port 3000');
});

步骤2:修改JS前端的请求地址

将请求地址改为宿主机映射的端口(本地开发用http://localhost:5001/,远程服务器替换为服务器公网IP+5001),同时移除mode: 'no-cors':

fetch('http://localhost:5001/')
  .then(res => res.json())
  .then(data => {
    console.table(data);
    // 渲染商品列表到页面
    const list = document.querySelector('ul');
    data.products.forEach(item => {
      const li = document.createElement('li');
      li.textContent = item;
      list.appendChild(li);
    });
    return data;
  })
  .catch(e => {
    console.error('请求失败:', e);
    return e;
  });

解决方案二:用Nginx反向代理避免跨域和域名问题

通过Nginx将前端的/api路径代理到Docker内部的API服务,前端用相对路径请求,无需处理跨域和外部IP:

步骤1:创建Nginx配置文件

在项目根目录新建nginx.conf:

server {
    listen 80;
    root /usr/share/nginx/html;
    index index.html index.htm;

    # 将/api路径代理到内部API服务
    location /api {
        proxy_pass http://api:3000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

步骤2:修改docker-compose.yml的client服务

挂载Nginx配置文件:

version: '3'
services:
  api:
    build: .
    volumes:
      - .:/home/node/app
    ports:
      - 5001:3000
  client:
    image: nginx
    volumes:
      - ./clientjs:/usr/share/nginx/html/
      - ./nginx.conf:/etc/nginx/conf.d/default.conf # 新增挂载配置
    ports:
      - 5002:80
    depends_on:
      - api
  php-client:
    image: php:apache
    volumes:
      - ./clientphp:/var/www/html
    ports: 
      - 5003:80
    depends_on:
      - api

步骤3:修改JS前端的请求路径

使用相对路径/api请求:

fetch('/api')
  .then(res => res.json())
  .then(data => {
    console.table(data);
    // 渲染商品列表
    const list = document.querySelector('ul');
    data.products.forEach(item => {
      const li = document.createElement('li');
      li.textContent = item;
      list.appendChild(li);
    });
    return data;
  })
  .catch(e => {
    console.error('请求失败:', e);
    return e;
  });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 08:55:17