【问题标题】:Azure Web App multi-container, hitting against CORS regardless of settingsAzure Web App 多容器,无论设置如何都会打击 CORS
【发布时间】:2020-12-31 02:31:20
【问题描述】:

概述

我有一个使用 Vue 的前端和一个使用 FastAPI 的后端。

我已经制作了两者的 Docker 容器和一个 docker-compose.yml 来将它们连接在一起。当我开发时,这一切都在本地运行良好。

当我将它移动到 Azure 时,我收到了一个 CORS 错误,特别是 Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://<my-site>.azurewebsites.net:8080/login

我看过几个CORS questions (here is another) 和Azure multi-container tutorials (another one, yet anotherone last one)。这些建议都没有解决问题,但没有一个是我的确切情况:

  • Azure 网络应用程序
  • 使用多容器
  • 具有单独的前端 (Vue) 和后端 (FastAPI)

代码

以下是我的代码的相关部分:

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:

前端 Dockerfile

# 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;"]

前端 Axios 代码

import axios from "axios";

export default () => {
  return axios.create({
    baseURL: `https://<my-site>.azurewebsites.net:8080/`,
    headers: { "Access-Control-Allow-Origin": "*" },
  });
};

后端 Dockerfile

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

后端 FastAPI 代码

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

我知道其中的大部分内容都太松散了...一旦我可以解决任何问题,我就会修复它。


Azure 命令

首先,我read that只识别端口80和8080,所以我把我的FE放在80上,把我的BE放在8080上。

接下来,这些是相关的 Azure 命令,一旦我将容器向上推:

  1. az webapp create -g &lt;my-rg&gt; -p &lt;my-plan&gt; -n &lt;app-name&gt; --multicontainer-config-file ./docker-compose.yml --multicontainer-config-type COMPOSE --assign-identity /subscriptions/&lt;my-subscription/resourceGroups/&lt;my-rg&gt;/providers/Microsoft.ManagedIdentity/userAssignedIdentities/&lt;my-userid&gt;
  2. az webapp config appsettings set -g &lt;my-rg&gt; -n &lt;my-app&gt; --settings WEBSITES_PORT=80
  3. az role assignment create --assignee &lt;my-info&gt; --scope /subscriptions/&lt;my-subscription&gt;/resourceGroups/&lt;my-rg&gt;/providers/Microsoft.ContainerRegistry/registries/&lt;my-acr&gt; --role "AcrPull"
  4. az webapp cors add -g &lt;my-rg&gt; -n &lt;app-name&gt; --allowed-origins "*"
  5. az webapp config container set -n &lt;app-name&gt; -g &lt;my-rg&gt; --multicontainer-config-file ./docker-compose.yml --multicontainer-config-type COMPOSE --docker-registry-server-url https://&lt;my-site&gt;.azurecr.io
  6. az webapp restart -n &lt;app-name&gt; -g &lt;my-rg&gt;

上面提到的docker-compose.yml与前面显示的相同。


我可以很好地看到所有前端,但是任何时候前端尝试到达后端时,它都会挂起一段时间,然后返回 Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://&lt;my-site&gt;.azurewebsites.net:8080 错误。

我也无法直接访问后端,要么只是查看原始 API,要么使用 FastAPI 自动生成的 docs 页面。

【问题讨论】:

  • 所有请求(GET/POST/PUT 等...)都有同样的问题吗?您能否打开浏览器控制台,然后为一个因 CORS 失败的 http 请求添加 requestresponse 的原始标头。
  • 确保对 OAuth 登录端点使用浏览器导航,而不是通过 axios 发出 XHR 请求,这是陷阱之一。
  • @DipenShah 你能解释一下你的意思吗?我不确定“OAuth 的浏览器导航”是什么意思?我会用什么来代替 axios?
  • 如果您无法访问 swagger 文档 - 这可能意味着您的 FastAPI 容器根本没有启动。您可以检查日志或以其他方式验证容器是否运行?
  • @MikeWilliamson 我的意思是确保您没有从 Axiom 调用 /login 端点,而是使用 a 标签或 window.location 将用户重定向到 /login 端点。跨度>

标签: azure vue.js web-services docker-compose fastapi


【解决方案1】:

我必须承认,我从未在应用服务中运行过包含前端和后端的多容器部署,只有自包含应用或单容器应用。说了这么多……

我认为这里有几个问题。

首先是为什么你不能从外部连接到你的后端服务。

如果您使用基于 Linux 的 Azure 应用服务,根据 Azure documentation,在多容器部署中,只有一个容器可以通过 Internet 访问。哪一个?以下是规则:

以下是确定哪个容器可访问的规则 - 按优先顺序排列:

  • 应用程序设置 WEBSITES_WEB_CONTAINER_NAME 设置为容器名称
  • 第一个定义端口 80 或 8080 的容器
  • 如果以上都不是,文件中定义的第一个容器将是可访问的(暴露的)

(抱歉,我无法正确格式化列表)。

这可能是无法从外部访问 backend 容器的原因,如果两个容器都应该从 Internet 访问,那么将部署更改为两个单容器的将是一个很好的理由.

另一个问题是您收到 CORS 错误的原因。

有几件事可能会导致问题。

一方面,只要您的前端不需要以这种方式使用,就不需要为您的 Web 应用程序配置 CORS。所以这个配置是没有必要的:

az webapp cors add -g <my-rg> -n <app-name> --allowed-origins "*"

出于同样的原因,您不需要在 Axios 中配置 CORS,因此您可以安全地从代码中删除以下配置行:

headers: { "Access-Control-Allow-Origin": "*" },

还有一个问题:如何通过frontend 联系backend 服务?

首先,看起来您的FastAPI 配置是正确的。

正如我在评论中提出的,我最好的建议是配置 Axios 客户端以利用 docker 内部网络并将 Axios 配置为使用 backend 作为发送请求的主机。

如果您查看您指出的第一个多容器示例 (https://docs.microsoft.com/en-us/azure/app-service/tutorial-multi-container-app),当他们配置 Wordpress 容器时,他们在其配置属性中引用 db 作为主机名,db 是暴露的服务:

WORDPRESS_DB_HOST: db:3306

简而言之,我认为多容器设置最适合当您拥有一项服务以及该服务正常运行所需的多种资源(SQL 数据库、Kafka、Redis)时的用例。

如果您不需要从外部访问您的后端,仅通过您的前端,它也可能是合适的。

在任何其他情况下,具有两个单容器 Web 应用程序的部署应该更合适。

最后一个想法...如果您一定需要实现多容器解决方案,也许您可​​以包含某种网络服务器,如 nginx,反向代理的想法也如 @timur 的评论中所建议的那样,您可以公开在80 端口,并定义访问前端和后端服务的规则。应该对其进行测试,但这可以帮助您大大简化 CORS 设置,甚至避免使用它。

【讨论】:

  • 我想知道在反向代理后面放置两个容器是否允许 OP 绕过单个可见容器限制
  • 对不起@timur,我刚看到你的评论。非常感谢。是的,确实应该尝试,但我认为它也可能是一个可能的解决方案。事实上,我已经用与您的提议类似的内容更新了我的答案。
  • @timur 我再次更新了答案以反映您的贡献。
  • 非常感谢@jccampanero。我还没有机会尝试这个,但是赏金时间很快就用完了(我希望它给更多的时间),所以我想在它到期之前奖励赏金。一旦我确认这解决了它,我也会接受答案。
  • 非常感谢迈克。我希望答案能帮助你解决你的问题。如果您认为我可以提供任何帮助,请随时继续在帖子上发帖,我很乐意为您提供尽可能多的帮助。
【解决方案2】:

在远程机器上使用 Docker 部署应用程序时,我们在前端遇到这些问题,即使后端工作正常,前端也会返回 CORS 问题。 为了解决这个问题,我们允许在响应中使用以下标头

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

【讨论】:

  • 是的,我已经设置了所有这些,除了允许标题,我现在就试试。
【解决方案3】:

在 Azure WebApp 中使用多容器目前不支持 CORS。而且正如其他人所提到的,您只能将一个容器暴露给外界(仅支持端口 80/8080)。

From the Azure Documentation:

预览限制

多容器目前处于预览阶段。不支持以下应用服务平台功能:

  • 身份验证/授权
  • 托管身份
  • CORS
  • Docker Compose 方案不支持 VNET 集成
  • Azure 应用服务上的 Docker Compose 目前限制为 4,000 个字符。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-26
    • 2019-02-10
    • 2015-09-22
    • 2021-04-17
    • 2016-07-13
    • 1970-01-01
    相关资源
    最近更新 更多