英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论