一直在努力让 FastAPI 应用程序在 azure 上运行。以下是所有步骤和发现:
FastAPI 端点:
from fastapi import FastAPI,Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi_azure_auth import SingleTenantAzureAuthorizationCodeBearer
import uvicorn
from fastapi import FastAPI, Security
import os
from typing import Dict
from settings import Settings
from pydantic import AnyHttpUrl,BaseModel
from contextlib import asynccontextmanager
from typing import AsyncGenerator
from fastapi_azure_auth.user import User
settings = Settings()
@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
"""
Load OpenID config on startup.
"""
await azure_scheme.openid_config.load_config()
yield
app = FastAPI(
swagger_ui_oauth2_redirect_url='/oauth2-redirect',
swagger_ui_init_oauth={
'usePkceWithAuthorizationCodeGrant': True,
'clientId': settings.OPENAPI_CLIENT_ID,
'scopes': settings.SCOPE_NAME,
},
)
if settings.BACKEND_CORS_ORIGINS:
app.add_middleware(
CORSMiddleware,
allow_origins=[str(origin) for origin in settings.BACKEND_CORS_ORIGINS],
allow_credentials=True,
allow_methods=['*'],
allow_headers=['*'],
)
azure_scheme = SingleTenantAzureAuthorizationCodeBearer(
app_client_id=settings.APP_CLIENT_ID,
tenant_id=settings.TENANT_ID,
scopes=settings.SCOPES,
)
class User(BaseModel):
name: str
roles: list[str] = []
@app.get("/", dependencies=[Security(azure_scheme)])
async def root():
print("Yo bro")
return {"whoIsTheBest": "DNA Team is"}
@app.get("/test", dependencies=[Security(azure_scheme)])
async def root():
print("Yo test")
return {"whoIsTheBest": "DNA Team is!"}
@app.get("/me", dependencies=[Security(azure_scheme)])
async def me(request: Request):
print("Me")
return User(roles=request.state.user.roles,name=request.state.user.name)
if __name__ == '__main__':
uvicorn.run('main:app', reload=True)
设置:
from pydantic import AnyHttpUrl, computed_field
from pydantic_settings import BaseSettings
import os
class Settings(BaseSettings):
BACKEND_CORS_ORIGINS: list[str | AnyHttpUrl] = ['http://localhost:80']
OPENAPI_CLIENT_ID: str = os.getenv('OPENAPI_CLIENT_ID')
APP_CLIENT_ID: str = os.getenv('APP_CLIENT_ID')
TENANT_ID: str = os.getenv('TENANT_ID')
SCOPE_DESCRIPTION: str = "user_impersonation"
@computed_field
@property
def SCOPE_NAME(self) -> str:
return f'api://{self.APP_CLIENT_ID}/{self.SCOPE_DESCRIPTION}'
@computed_field
@property
def SCOPES(self) -> dict:
return {
self.SCOPE_NAME: self.SCOPE_DESCRIPTION,
}
@computed_field
@property
def OPENAPI_TOKEN_URL(self) -> str:
return f"https://login.microsoftonline.com/{self.TENANT_ID}/oauth2/v2.0/token"
class Config:
env_file = '.env'
env_file_encoding = 'utf-8'
case_sensitive = True
我在 github 中有以下操作: 名称:构建 Python 应用程序并将其部署到 Azure Web App - fast-api-port
on:
push:
branches:
- main
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python version
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Create and start virtual environment
run: |
python -m venv venv
source venv/bin/activate
- name: Install dependencies
run: pip install -r requirements.txt
# Optional: Add step to run tests here (PyTest, Django test suites, etc.)
- name: Zip artifact for deployment
run: zip release.zip ./* -r
- name: Upload artifact for deployment jobs
uses: actions/upload-artifact@v4
with:
name: python-app
path: |
release.zip
!venv/
deploy:
runs-on: ubuntu-latest
needs: build
environment:
name: 'Production'
url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
permissions:
id-token: write #This is required for requesting the JWT
steps:
- name: Download artifact from build job
uses: actions/download-artifact@v4
with:
name: python-app
- name: Unzip artifact for deployment
run: unzip release.zip
- name: Login to Azure
uses: azure/login@v2
with:
client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_7C6D249DE594426EBD4725CC0D066145 }}
tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_6399B578ADAF41E095CA377A465B8BB1 }}
subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_527AF2EA4A6A4A8BAC99ECB57B6CE6AB }}
- name: 'Deploy to Azure Web App'
uses: azure/webapps-deploy@v3
id: deploy-to-webapp
with:
app-name: 'fast-api-port'
slot-name: 'Production'
我可以看到文件按预期部署到 Web 应用程序中 wwwroot 文件夹中的 output.tar.gz 文件。
当我加载我的应用程序时https://xxx.westeurope-01.azurewebsites.net/docs我收到以下错误:
有什么建议会导致这种情况吗?
当我使用你的代码并使用 GitHub 将其部署到 Azure 时,我遇到了同样的错误。
如果仔细观察应用程序日志,我们可以看到环境变量 OPENAPI_CLIENT_ID、APP_CLIENT_ID 和 TENANT_ID 的
input_value
设置为 None
。因此,该应用程序无法启动。
为了解决上述问题,我将以下值从
.env
文件添加到 Azure Web App 的 Environment Variables
。
TENANT_ID=<Tenant_Id>
APP_CLIENT_ID=<App_Client_Id>
OPENAPI_CLIENT_ID=<Openapi_Client_Id>
Azure 输出: