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

Azure部署双容器Docker Compose应用的CORS问题解决求助

双容器Docker Compose应用部署Azure后前后端通信问题

问题现象

部署后前端调用后端API时出现以下错误:

"Blocked loading mixed active content “http://backend:9000/api/weather”"
临时禁用浏览器安全保护后,错误变为:
"Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://backend:9000/api/weather. (Reason: CORS request did not succeed). Status code: (null)."

现有配置

docker-compose.yml

version: "3.8"
services:
  frontend:
    image: my_frontend_image
    build:
        context: .
    container_name: frontend
    ports:
      - "80:8000"
    environment:
      - PORT=8000
      - ENDPOINT=http://backend:9000/api
      - HOST=0.0.0.0
  backend:
    image: my_backend_image
    build:
        context: .
    container_name: backend
    environment:
      - PORT=9000
      - MAP_ENDPOINT=http://api.openweathermap.org/data/2.5
      - TARGET_CITY=Helsinki,fi
      - APPID=my_api_key

后端Koa配置

CORS配置(index.js):

const cors = require('kcors');

const app = new Koa();

app.use(cors());

路由配置(index.js):

const port = process.env.PORT;

const router = require('koa-router')();

router.get('/api/weather', async ctx => {
  const weatherData = await fetchWeather();

  ctx.type = 'application/json; charset=utf-8';
  ctx.body = weatherData.weather ? weatherData.weather[0] : {};
});

app.use(router.routes());
app.use(router.allowedMethods());

app.listen(port);

前端请求代码(index.jsx)

const baseURL = process.env.ENDPOINT;

const getWeatherFromApi = async () => {
  try {
    const response = await fetch(`${baseURL}/weather`);
    return response.json();
  } catch (error) {
    console.error(error);
  }

  return {};
};

Webpack配置(webpack.config.js)

const GLOBALS = {
  'process.env.ENDPOINT': JSON.stringify(process.env.ENDPOINT || 'http://0.0.0.0:9000/api'),
};

module.exports = {
...
  plugins: [
    ...
    new webpack.DefinePlugin(GLOBALS),
]
};

本地与云端差异

  • 本地运行:将ENDPOINT设为http://localhost:9000/api,并在docker-compose中映射9000:9000,可正常工作。
  • 本地容器测试:容器间可ping通,curl访问API正常:
docker exec -it frontend bash
root@e87994510b0e:/app# ping backend
PING backend (172.25.0.2) 56(84) bytes of data.
64 bytes from backend.efi-recruitment_default (172.25.0.2): icmp_seq=1 ttl=64 time=0.059 ms
64 bytes from backend.efi-recruitment_default (172.25.0.2): icmp_seq=2 ttl=64 time=0.117 ms
64 bytes from backend.efi-recruitment_default (172.25.0.2): icmp_seq=3 ttl=64 time=0.115 ms
root@e87994510b0e:/app# curl http://backend:9000/api/weather
{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}

解决步骤

核心问题

云端部署后,前端代码在用户浏览器中执行,浏览器无法识别Docker内部的backend主机名——Docker DNS仅在容器内部网络生效,浏览器不在该网络环境中。此外,如果Azure前端使用HTTPS默认配置,请求HTTP的backend地址会触发混合内容拦截。

方案一:反向代理(推荐)

通过前端容器转发请求到后端,避免跨域和主机名问题:

  1. 修改前端环境变量ENDPOINT为相对路径:
    frontend:
      environment:
        - ENDPOINT=/api
    
  2. 在前端容器中配置反向代理:
    • 如果前端用Nginx作为静态服务器,添加Nginx配置:
      location /api {
          proxy_pass http://backend:9000/api;
      }
      
    • 如果前端是Node服务,可使用http-proxy-middleware等工具实现代理。
  3. 重新构建镜像并部署到Azure,前端通过相对路径/api/weather发起请求,由前端容器转发到后端服务。

方案二:配置公开后端地址与CORS

若不使用反向代理,需让后端可被公网访问并配置正确CORS:

  1. 在Azure中为后端服务配置公网访问地址(如负载均衡器、App Service域名),确保使用HTTPS。
  2. 更新前端ENDPOINT为后端公开HTTPS地址,例如https://your-backend-azure-domain.com/api。
  3. 修改后端CORS配置,允许前端云端域名:
    app.use(cors({
      origin: 'https://your-frontend-azure-domain.com', // 替换为实际前端域名
      credentials: true
    }));
    
  4. 重新部署前后端服务,验证请求正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 12:15:21