Reputation: 3158
I have a frontend using Vue and a backend using FastAPI.
I have made Docker containers of both and a docker-compose.yml
to hook it all together. It all works fine locally when I am developing.
When I move it to Azure, I am receiving a CORS error, specifically Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://<my-site>.azurewebsites.net:8080/login
.
I have looked at several CORS questions (here is another) and Azure multi-container tutorials (another one, yet another and one last one). None of the suggestions solved the problem, but none of them were my exact situation:
Here are the relevant parts of my code:
docker-compose.yml
version: "3.8"
services:
frontend:
image: <my-acr>.azurecr.io/<my-fe-image>:1
networks:
- fullstack
ports:
- "80:80"
backend:
image: <my-acr>.azurecr.io/<my-be-image>:1
networks:
- fullstack
ports:
- "8080:80"
networks:
fullstack:
# develop stage
FROM node:14.8-alpine3.12 as develop-stage
ENV CONTAINER_PATH /vue
WORKDIR $CONTAINER_PATH
COPY package*.json ./
RUN yarn install
COPY . .
# build stage
FROM develop-stage as build-stage
RUN ["yarn", "build"]
# production stage
FROM nginx:1.19.2-alpine as production-stage
COPY --from=build-stage /vue/dist /usr/share/nginx/html
EXPOSE 8080 2222 80 443
CMD ["nginx", "-g", "daemon off;"]
import axios from "axios";
export default () => {
return axios.create({
baseURL: `https://<my-site>.azurewebsites.net:8080/`,
headers: { "Access-Control-Allow-Origin": "*" },
});
};
FROM tiangolo/uvicorn-gunicorn:python3.8
RUN ["pip", "install", "--upgrade", "pip"]
RUN ["pip", "install", "--upgrade", "--ignore-installed", \
"--use-feature=2020-resolver", "--no-cache-dir", "jwcrypto", "fastapi", "passlib", \
"sqlalchemy", "toml", "topicaxis-opengraph", "sqlalchemy_imageattach", \
"email_validator", "bcrypt"]
EXPOSE 8080 2222 80 443
COPY ./src /app
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
I know much of that is too loose... I will fix it once I can get anything to work.
First, I read that only ports 80 and 8080 are recognized, so I put my FE on 80 and my BE on 8080.
Next, these are the relevant Azure commands, once I pushed the containers up:
az webapp create -g <my-rg> -p <my-plan> -n <app-name> --multicontainer-config-file ./docker-compose.yml --multicontainer-config-type COMPOSE --assign-identity /subscriptions/<my-subscription/resourceGroups/<my-rg>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<my-userid>
az webapp config appsettings set -g <my-rg> -n <my-app> --settings WEBSITES_PORT=80
az role assignment create --assignee <my-info> --scope /subscriptions/<my-subscription>/resourceGroups/<my-rg>/providers/Microsoft.ContainerRegistry/registries/<my-acr> --role "AcrPull"
az webapp cors add -g <my-rg> -n <app-name> --allowed-origins "*"
az webapp config container set -n <app-name> -g <my-rg> --multicontainer-config-file ./docker-compose.yml --multicontainer-config-type COMPOSE --docker-registry-server-url https://<my-site>.azurecr.io
az webapp restart -n <app-name> -g <my-rg>
The docker-compose.yml
mentioned above is the same one that is shown earlier.
I am able to see all of the front end fine, but any time the front-end tries to reach the back end, it hangs for a while and then comes back with the Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://<my-site>.azurewebsites.net:8080
error.
I am also unable to hit the back end directly, either just to see the raw API, or using FastAPI's auto-generated docs
page.
Upvotes: 1
Views: 1724
Reputation: 686
Using multi container in Azure WebApp currently doesn't support CORS. And as others have mentioned, you can only expose one container to the outside world (only port 80/8080 is supported).
Preview limitations
Multi-container is currently in preview. The following App Service platform features are not supported:
Upvotes: 0
Reputation: 415
We face these issues on the front end side when deploying an application using Docker in remote machines, even though the back end works fine, the front end returns CORS issues. To fix this, we allow the following headers in the response
"Content-Type": "application/json"
"Access-Control-Allow-Origin": "*"
"Access-Control-Allow-Methods": 'POST, GET, PUT, DELETE, OPTIONS'
"Access-Control-Allow-Headers": "Access-Control-Allow-Origin,Authorization, "Access-Control-Allow-Methods,"Content-Type"
Upvotes: 1
Reputation: 53381
I must admit that I never ran a multi-container deployment in App Service with frontend and backend, only self-contained apps or single container ones. Having said that...
I think there are several problems here.
The first is why you can't connect to your backend service externally.
If you are using a Linux based Azure App Service, according to the Azure documentation, in a multi-container deployment, only one container is open to access over the internet. Which one? Here are the rules:
Here are the rules for determining which container is accessible - in the order of precedence:
(Sorry, I was unable to format the list correctly).
This may be the reason why the backend
container is not accessible from the externally, and, if both containers should be accessed from the internet, it will be a good reason to change your deployment for two single-container ones instead.
Another problem is why you are getting the CORS error.
There are several things that could cause the problem.
On one hand, it is not necessary to configure CORS for your web app as long as your frontend need not to be consumed in that way. So this configuration is not necessary:
az webapp cors add -g <my-rg> -n <app-name> --allowed-origins "*"
For the same reason, you do not need to configure CORS in Axios, so you can safely remove the following configuration line from your code:
headers: { "Access-Control-Allow-Origin": "*" },
And a question remains: how can you contact your backend
service from your frontend
?
First of all, it looks like your FastAPI
configuration is right.
As proposed in my comment, my best advice is that you configure your Axios client to take advantage of the docker internal networking and configure Axios to use backend
as the host to which sent their requests.
If you review the first multi-container example that you indicated (https://learn.microsoft.com/en-us/azure/app-service/tutorial-multi-container-app), when they configure the Wordpress container, they are referencing, in their configuration properties, db
as the hostname, being db
an exposed service:
WORDPRESS_DB_HOST: db:3306
In short, I think the multi-container setup is best suited for use cases when you have a service and multiple resources (SQL databases, Kafka, Redis) required for that service to function properly.
It might also be appropriate if you don't need to access your backend externally, only through your frontend.
In any other case, a deployment with two single container web applications should be more suitable.
One last thought ... If you necessarily need to implement a multi-container solution, maybe you can include some kind of webserver like nginx, the idea of a reverse proxy as also suggested in @timur's comment, that you can expose at the 80
port, and define rules to access the frontend and backend services. It should be tested, but this could help you greatly simplify your CORS setup and even avoid the need to use it.
Upvotes: 4