How to fix CORS issue when deploying a 2 container docker-compose app to Azure and communicating between frontend and backend using REST API?

huangapple go评论89阅读模式
英文:

How to fix CORS issue when deploying a 2 container docker-compose app to Azure and communicating between frontend and backend using REST API?

问题

I am trying to deploy a 2 container docker-compose app to Azure, consisting of a frontend and backend/api. I need the frontend container to communicate with the backend container using the fetch method to retrieve some data using REST API.

Once deployed I first get:

"Blocked loading mixed active content “http://backend:9000/api/weather”"

then once I disable the protection temporarily, the error becomes

"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)."

This is my 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

The frontend container exposes port 8000, backend container exposes 9000 in their respective Dockerfiles.

My backend is using kcors:

index.js

const cors = require('kcors');

const app = new Koa();

app.use(cors());

And the koa router:

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);

My frontends request looks like this:

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.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),
]
};

I managed to get the app working locally, by setting my api endpoint to http://localhost:9000/api and mapping "9000:9000" in my docker-compose. I cannot however get this to work in the cloud...

Locally, I tried pinging each container from within one another, which worked with no problem.

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

Trying to access the api using curl also worked:

root@e87994510b0e:/app# curl http://backend:9000/api/weather
{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}

This is the first time I'm trying to deploy something to Azure and I am quite lost. Any help would be greatly appreciated.

英文:

I am trying to deploy a 2 container docker-compose app to Azure, consisting of a frontend and backend/api. I need the frontend container to communicate with the backend container using the fetch method to retrieve some data using REST API.

Once deployed I first get:

> "Blocked loading mixed active content “http://backend:9000/api/weather”"

then once I disable the protection temporarily, the error becomes

> "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).".

This is my 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

The frontend container exposes port 8000, backend container exposes 9000 in their respective Dockerfiles.

My backend is using kcors:

index.js

const cors = require('kcors');

const app = new Koa();

app.use(cors());

And the koa router:

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);

My frontends request looks like this:

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.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),
]
};

I managed to get the app working locally, by setting my api endpoint to http://localhost:9000/api and mapping "9000:9000" in my docker-compose. I cannot however get this to work in the cloud...

Locally, I tried pinging each container from within one another, which worked with no problem.

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

Trying to access the api using curl also worked:

root@e87994510b0e:/app# curl http://backend:9000/api/weather
{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}

This is the first time I'm trying to deploy something to Azure and I am quite lost. Any help would be greatly appreciated.

答案1

得分: 0

您的前端用户的浏览器调用您的后端。您的后端不暴露在互联网上,无法访问。

将您的后端放置在另一个容器化的Web应用程序中,并更新您的URL。这应该解决您的问题。

英文:

Your frontend calls your backend from user's browser. Your backend is not exposed on the Internet and cannot be reached.

Place your backend in another Web App for container and update your URLs. This should solve your problem.

huangapple
  • 本文由 发表于 2023年5月30日 02:11:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76359512.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定