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地址会触发混合内容拦截。
方案一:反向代理(推荐)
通过前端容器转发请求到后端,避免跨域和主机名问题:
- 修改前端环境变量
ENDPOINT为相对路径:frontend: environment: - ENDPOINT=/api - 在前端容器中配置反向代理:
- 如果前端用Nginx作为静态服务器,添加Nginx配置:
location /api { proxy_pass http://backend:9000/api; } - 如果前端是Node服务,可使用
http-proxy-middleware等工具实现代理。
- 如果前端用Nginx作为静态服务器,添加Nginx配置:
- 重新构建镜像并部署到Azure,前端通过相对路径
/api/weather发起请求,由前端容器转发到后端服务。
方案二:配置公开后端地址与CORS
若不使用反向代理,需让后端可被公网访问并配置正确CORS:
- 在Azure中为后端服务配置公网访问地址(如负载均衡器、App Service域名),确保使用HTTPS。
- 更新前端
ENDPOINT为后端公开HTTPS地址,例如https://your-backend-azure-domain.com/api。 - 修改后端CORS配置,允许前端云端域名:
app.use(cors({ origin: 'https://your-frontend-azure-domain.com', // 替换为实际前端域名 credentials: true })); - 重新部署前后端服务,验证请求正常。
内容的提问来源于stack exchange,提问作者tranzzik
相关产品推荐
相关产品推荐

