你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
在 Azure 中部署使用 PostgreSQL 的 Python FastAPI Web 应用
在本教程中,你要将一个使用 Azure Database for PostgreSQL 关系数据库服务的数据驱动 Python Web 应用(FastAPI)部署到 Azure 应用服务。 Azure 应用服务支持 Linux 服务器环境中的 Python。
若要完成本教程,你需要:
- 具有活动订阅的 Azure 帐户。 如果没有 Azure 帐户,可以免费创建一个。
- Python 与 FastAPI 开发的知识
- 具有活动订阅的 Azure 帐户。 如果没有 Azure 帐户,可以免费创建一个。
- 已安装 Azure 开发人员 CLI。 可以使用 Azure Cloud Shell 执行这些步骤,因为它已安装 Azure 开发人员 CLI。
- Python 与 FastAPI 开发的知识
跳到末尾
安装 Azure Developer CLI 后,可以在空的工作目录中运行以下命令,跳到本教程末尾:
azd auth login
azd init --template msdocs-fastapi-postgresql-sample-app
azd up
示例应用程序
我们提供了使用 FastAPI 框架的示例 Python 应用程序来帮助你学习本教程。 若要部署该应用程序但不在本地运行它,请跳过本部分。
若要在本地运行应用程序,请确保在本地安装 Python 3.8 或更高版本和 PostgreSQL。 然后克隆示例存储库的 starter-no-infra
分支,并更改为存储库根路径。
git clone -b starter-no-infra https://github.com/Azure-Samples/msdocs-fastapi-postgresql-sample-app
cd msdocs-fastapi-postgresql-sample-app
使用 .env.sample 文件作为指南创建 .env 文件,如下所示。 将 DBNAME
的值设置为本地 PostgreSQL 实例中现有数据库的名称。 根据本地 PostgreSQL 实例设置相应的 DBHOST
、DBUSER
和 DBPASS
值。
DBNAME=<database name>
DBHOST=<database-hostname>
DBUSER=<db-user-name>
DBPASS=<db-password>
为应用创建一个虚拟环境:
py -m venv .venv
.venv\scripts\activate
安装依赖项:
python3 -m pip install -r src/requirements.txt
将应用作为可编辑包安装:
python3 -m pip install -e src
使用以下命令运行示例应用程序:
# Run database migration
python3 src/fastapi_app/seed_data.py
# Run the app at http://127.0.0.1:8000
python3 -m uvicorn fastapi_app:app --reload --port=8000
1. 创建应用服务和 PostgreSQL
此步骤创建 Azure 资源。 本教程中使用的步骤创建一组默认安全的资源,其中包括应用服务和 Azure Database for PostgreSQL。 对于创建过程,需要指定:
- Web 应用的名称。 此名称用作 Web 应用的 DNS 名称的一部分,其格式为
https://<app-name>.azurewebsites.net
。 - “区域”,在世界上以物理方式运行应用。
- 应用的运行时堆栈。 在此处选择要用于应用的 Python 版本。
- 应用的托管计划。 它是定价层,包括应用的一组功能和缩放容量。
- 应用的资源组。 使用资源组可将应用程序所需的所有 Azure 资源分组到一个逻辑容器中。
登录到 Azure 门户并按照以下步骤创建 Azure 应用服务资源。
步骤 1:在 Azure 门户中:
- 在 Azure 门户顶部的搜索栏中,输入“Web 应用数据库”。
- 选择“市场”标题下标记为“Web 应用 + 数据库”的项目。 还可以直接导航到创建向导。
步骤 2:在“创建 Web 应用 + 数据库”页上,按下面所述填写表单。
- 资源组 → 选择“新建”,然后使用名称 msdocs-python-postgres-tutorial。
- 区域 → 与你靠近的任何 Azure 区域。
- 名称 → msdocs-python-postgres-XYZ,其中 XYZ 是任意三个随机字符。 该名称在 Azure 中必须唯一。
- 运行时堆栈 → Python 3.12。
- 数据库 → 默认已选择“PostgreSQL 灵活服务器”作为数据库引擎。 默认情况下,服务器名称和数据库名称也会设置为适当的值。
- 托管计划 → 基本。 准备就绪后,可以稍后纵向扩展到生产定价层。
- 选择“查看 + 创建”。
- 验证完成后,选择“创建”。
步骤 3:该部署需要数分钟才能完成。 部署完成后,选择“转到资源”按钮。 这将直接转到应用服务应用,但会创建以下资源:
- 资源组 → 所有已创建资源的容器。
- 应用服务计划 → 定义应用服务的计算资源。 将创建基本层中的 Linux 计划。
- 应用服务 → 表示应用,且在应用服务计划中运行。
- 虚拟网络 → 与应用服务应用集成,并隔离后端网络流量。
- Azure Database for PostgreSQL 灵活服务器 → 只能从虚拟网络内部访问。 你的数据库和用户创建于此服务器上。
- 专用 DNS 区域 → 在虚拟网络中启用 PostgreSQL 服务器的 DNS 解析。
步骤 4:对于 FastAPI 应用,必须输入启动命令,以便应用服务可以启动应用。 在“应用服务”页上:
- 在左侧菜单中的“设置”下选择“配置”。
- 在“配置”页的“常规设置”选项卡中,在“堆栈设置”下的“启动命令”字段中输入
src/entrypoint.sh
。 - 选择“保存”。 出现提示时,选择“继续”。 若要了解有关应用服务中的应用配置和启动的详细信息,请参阅为 Azure 应用服务配置 Linux Python 应用。
2. 验证连接设置
创建向导已经为你生成了连接变量作为应用设置。 使用应用设置可以将连接机密保留在代码存储库之外。 准备好将机密移动到更安全的位置后,下面提供了一篇有关在 Azure 密钥保管库中存储的文章。
步骤 1:在左侧菜单的“应用服务”页面中,选择“环境变量”。
步骤 2:在“环境变量”页的“应用设置”选项卡中,验证 AZURE_POSTGRESQL_CONNECTIONSTRING
是否存在。 连接字符串将作为环境变量注入到运行时环境中。
3. 部署示例代码
在此步骤中,使用 GitHub Actions 配置 GitHub 部署。 这只是部署到应用服务的许多方法之一,也是一种在部署过程中持续集成的好方法。 默认情况下,GitHub 存储库的每个 git push
都会启动生成和部署操作。
步骤 1:在新浏览器窗口中:
- 登录到 GitHub 帐户。
- 导航到 https://github.com/Azure-Samples/msdocs-fastapi-postgresql-sample-app。
- 选择“Fork”。
- 选择“创建分支”。
步骤 2:在 GitHub 页中,按 .
键在浏览器中打开 Visual Studio Code。
步骤 3:在浏览器中的 Visual Studio Code 中,在资源管理器中打开 src/fastapi/models.py。 查看生产环境中使用的环境变量,包括在配置页中看到的应用设置。
步骤 4:返回应用服务页面,在左侧菜单中的“部署”下,选择“部署中心”。
步骤 5:在“部署中心”页中:
- 在“源”中,选择“GitHub”。 默认情况下,选择 GitHub Actions 作为生成提供程序。
- 登录到 GitHub 帐户,并按照提示授权 Azure。
- 在“组织”中,选择你的帐户。
- 在“存储库”中,选择“msdocs-fastapi-postgresql-sample-app”。
- 在“分支”中,选择“主”。
- 保留所选的默认选项以添加工作流。
- 在“身份验证类型”下,选择“用户分配的标识”。
- 在顶部菜单中,选择“保存”。 应用服务会将工作流文件提交到所选 GitHub 存储库中(在
.github/workflows
目录中)。
步骤 6:在“部署中心”页中:
- 选择“日志”。 部署运行已启动。
- 在部署运行的日志项中,选择“生成/部署日志”。
步骤 7:你已转到 GitHub 存储库,并看到 GitHub Action 正在运行。 工作流文件定义两个单独的阶段,即生成和部署阶段。 等待 GitHub 运行以显示“完成”状态。 此过程大约需要 5 分钟。
遇到问题? 查看故障排除指南。
4. 生成数据库架构
在上一节中,你添加了 src/entrypoint.sh 作为应用的启动命令。 entrypoint.sh 包含以下行:python3 src/fastapi_app/seed_data.py
。 此命令将迁移数据库。 在示例应用中,它仅确保在数据库中创建正确的表。 它不会使用任何数据填充这些表。
在本节中,你将手动运行此命令以进行演示。 在 PostgreSQL 数据库受虚拟网络保护的情况下,运行该命令的最简单方法是使用应用服务容器在 SSH 会话中运行。
步骤 1:返回“应用服务”页,在左侧菜单中,
- 选择“SSH”。
- 选择“转到”。
步骤 2:在 SSH 终端中运行 python3 src/fastapi_app/seed_data.py
。 如果该命令成功,则应用服务会成功连接到数据库。
只有对 /home
中文件的更改才能在应用重启之后持久保存。 不会保留 /home
外部的更改。
5.浏览到应用
步骤 1:在“应用服务”页中:
- 从左侧菜单中选择“概述”。
- 选择应用的 URL。 你也可以直接导航到
https://<app-name>.azurewebsites.net
。
步骤 2:在列表中添加几家餐厅。 恭喜,你已在 Azure 应用服务中运行了一个 Web 应用,并安全连接到了 Azure Database for PostgreSQL。
6.流式传输诊断日志
示例应用使用 Python 标准库日志记录模块来帮助诊断应用程序的问题。 示例应用包括对记录器的调用,如以下代码所示。
@app.get("/", response_class=HTMLResponse)
async def index(request: Request, session: Session = Depends(get_db_session)):
logger.info("root called")
statement = (
select(Restaurant, func.avg(Review.rating).label("avg_rating"), func.count(Review.id).label("review_count"))
.outerjoin(Review, Review.restaurant == Restaurant.id)
.group_by(Restaurant.id)
)
步骤 1:在“应用服务”页中:
- 从左侧菜单中的“监视”下,选择“应用服务日志”。
- 在“应用程序日志记录”下,选择“文件系统”。
- 在顶部菜单中,选择“保存”。
步骤 2:在左侧菜单中,选择“日志流”。 将显示应用的日志,包括平台日志和容器内部的日志。
事件可能需要几分钟才能显示在诊断日志中。 在为 Python 应用程序设置 Azure Monitor 系列文章中,详细了解 Python 应用中的日志记录。
7.清理资源
完成后,可以通过删除资源组从 Azure 订阅中删除所有资源。
步骤 1:在 Azure 门户顶部的搜索栏中:
- 输入资源组名称。
- 选择前面创建的资源组。
步骤 2:在资源组页上,选择“删除资源组”。
步骤 3:
- 输入资源组名称以确认删除。
- 选择“删除”。
1.创建 Azure 资源并部署示例应用
在此步骤中,将创建 Azure 资源并将示例应用部署到 Linux 上的应用服务。 本教程中使用的步骤创建一组默认安全的资源,其中包括应用服务和 Azure Database for PostgreSQL。
如果尚未执行以上操作,请在本地终端中克隆示例存储库的
starter-no-infra
分支。git clone -b starter-no-infra https://github.com/Azure-Samples/msdocs-fastapi-postgresql-sample-app cd msdocs-fastapi-postgresql-sample-app
此克隆分支是你的起点。 它包含简单的数据驱动 FastAPI 应用程序。
从存储库根路径,运行
azd init
。azd init --template msdocs-fastapi-postgresql-sample-app
出现提示时,请提供以下答案:
问题 Answer 当前目录不为空。 是否要在此处初始化“<your-directory>”中的项目? Y 你希望对这些文件执行哪些操作? 使现有文件保持不变 输入新环境名称 键入唯一名称。 azd 模板将此名称用作 Azure 中 Web 应用的 DNS 名称的一部分 ( <app-name>.azurewebsites.net
)。 允许使用字母数字字符和下划线。运行
azd up
命令以提供必要的 Azure 资源并部署应用代码。 如果尚未登录到 Azure,浏览器将启动并要求你登录。azd up
命令还将提示选择要部署到的所需订阅和位置。azd up
azd up
命令可能需要几分钟才能完成。 它还会编译和部署应用程序代码。 在运行时,该命令会提供有关预配和部署过程的消息,包括指向 Azure 中部署的链接。 完成后,命令还会显示指向部署应用程序的链接。此 azd 模板包含使用以下 Azure 资源生成安全默认体系结构的文件(azure.yaml 和 infra 目录):
- 资源组 → 所有已创建资源的容器。
- 应用服务计划 → 定义应用服务的计算资源。 已指定 B1 层中的 Linux 计划。
- 应用服务 → 表示应用,且在应用服务计划中运行。
- 虚拟网络 → 与应用服务应用集成,并隔离后端网络流量。
- Azure Database for PostgreSQL 灵活服务器 → 只能从虚拟网络内部访问。 你的数据库和用户创建于此服务器上。
- 专用 DNS 区域 → 在虚拟网络中启用 PostgreSQL 服务器的 DNS 解析。
- Log Analytics 工作区 →充当应用日志传送的目标容器,还可以在其中查询日志。
当
azd up
命令完成时,记下输出中的“订阅 ID”(Guid)、“应用服务”和“资源组”的值。 在下面的小节中使用它们。 输出的外观将与以下(部分)输出类似:Subscription: Your subscription name (1111111-1111-1111-1111-111111111111) Location: East US You can view detailed progress in the Azure Portal: https://portal.azure.com/#view/HubsExtension/DeploymentDetailsBlade/~/overview/id/%2Fsubscriptions%2F1111111-1111-1111-1111-111111111111%2Fproviders%2FMicrosoft.Resources%2Fdeployments%2Fyourenv-1721867673 (✓) Done: Resource group: yourenv-rg (✓) Done: Virtual Network: yourenv-e2najjk4vewf2-vnet (✓) Done: App Service plan: yourenv-e2najjk4vewf2-service-plan (✓) Done: Log Analytics workspace: yourenv-e2najjk4vewf2-workspace (✓) Done: Application Insights: yourenv-e2najjk4vewf2-appinsights (✓) Done: Portal dashboard: yourenv-e2najjk4vewf2-dashboard (✓) Done: App Service: yourenv-e2najjk4vewf2-app-service (✓) Done: Azure Database for PostgreSQL flexible server: yourenv-e2najjk4vewf2-postgres-server (✓) Done: Cache for Redis: yourenv-e2najjk4vewf2-redisCache (✓) Done: Private Endpoint: cache-privateEndpoint SUCCESS: Your application was provisioned in Azure in 32 minutes. You can view the resources created under the resource group yourenv-rg in Azure Portal: https://portal.azure.com/#@/resource/subscriptions/1111111-1111-1111-1111-111111111111/resourceGroups/yourenv-rg/overview Deploying services (azd deploy) (✓) Done: Deploying service web - Endpoint: https://yourenv-e2najjk4vewf2-app-service.azurewebsites.net/
2.检查数据库连接字符串
azd 模板会为你生成连接变量作为应用设置。 使用应用设置可以将连接机密保留在代码存储库之外。
在
infra/resources.bicep
文件中,找到应用设置,然后找到AZURE_POSTGRESQL_CONNECTIONSTRING
的设置。resource appSettings 'config' = { name: 'appsettings' properties: { SCM_DO_BUILD_DURING_DEPLOYMENT: 'true' AZURE_POSTGRESQL_CONNECTIONSTRING: 'dbname=${pythonAppDatabase.name} host=${postgresServer.name}.postgres.database.azure.com port=5432 sslmode=require user=${postgresServer.properties.administratorLogin} password=${databasePassword}' SECRET_KEY: secretKey AZURE_REDIS_CONNECTIONSTRING: 'rediss://:${redisCache.listKeys().primaryKey}@${redisCache.name}.redis.cache.windows.net:6380/0' } }
AZURE_POSTGRESQL_CONNECTIONSTRING
包含 Azure 中 Postgres 数据库的连接字符串。 需要在代码中使用它来连接它。 可以在 src/fastapi/models.py 中找到使用此环境变量的代码:sql_url = "" if os.getenv("WEBSITE_HOSTNAME"): logger.info("Connecting to Azure PostgreSQL Flexible server based on AZURE_POSTGRESQL_CONNECTIONSTRING...") env_connection_string = os.getenv("AZURE_POSTGRESQL_CONNECTIONSTRING") if env_connection_string is None: logger.info("Missing environment variable AZURE_POSTGRESQL_CONNECTIONSTRING") else: # Parse the connection string details = dict(item.split('=') for item in env_connection_string.split()) # Properly format the URL for SQLAlchemy sql_url = ( f"postgresql://{quote_plus(details['user'])}:{quote_plus(details['password'])}" f"@{details['host']}:{details['port']}/{details['dbname']}?sslmode={details['sslmode']}" ) else: logger.info("Connecting to local PostgreSQL server based on .env file...") load_dotenv() POSTGRES_USERNAME = os.environ.get("DBUSER") POSTGRES_PASSWORD = os.environ.get("DBPASS") POSTGRES_HOST = os.environ.get("DBHOST") POSTGRES_DATABASE = os.environ.get("DBNAME") POSTGRES_PORT = os.environ.get("DBPORT", 5432) sql_url = f"postgresql://{POSTGRES_USERNAME}:{POSTGRES_PASSWORD}@{POSTGRES_HOST}:{POSTGRES_PORT}/{POSTGRES_DATABASE}" engine = create_engine(sql_url)
3.检查启动命令
Azure 应用服务需要启动命令才能运行 FastAPI 应用。 azd 模板在应用服务实例中为你设置此命令。
在
infra/resources.bicep
文件中,找到网站的声明,然后找到appCommandLine
的设置。 这是启动命令的设置。resource web 'Microsoft.Web/sites@2022-03-01' = { name: '${prefix}-app-service' location: location tags: union(tags, { 'azd-service-name': 'web' }) kind: 'app,linux' properties: { serverFarmId: appServicePlan.id siteConfig: { alwaysOn: true linuxFxVersion: 'PYTHON|3.11' ftpsState: 'Disabled' appCommandLine: 'src/entrypoint.sh' minTlsVersion: '1.2' } httpsOnly: true } identity: { type: 'SystemAssigned' }
启动命令将运行文件 src/entrypoint.sh。检查该文件中的代码,以了解应用服务运行以启动应用的命令:
#!/bin/bash set -e python3 -m pip install --upgrade pip python3 -m pip install -e src python3 src/fastapi_app/seed_data.py python3 -m gunicorn fastapi_app:app -c src/gunicorn.conf.py
若要了解有关应用服务中的应用配置和启动的详细信息,请参阅为 Azure 应用服务配置 Linux Python 应用。
4. 生成数据库架构
你可能在上一节中已经注意到,entrypoint.sh 包含以下行:python3 src/fastapi_app/seed_data.py
。 此命令将迁移数据库。 在示例应用中,它仅确保在数据库中创建正确的表。 它不会使用任何数据填充这些表。
在本节中,你将手动运行此命令以进行演示。 在 PostgreSQL 数据库受虚拟网络保护的情况下,运行该命令的最简单方法是使用应用服务容器在 SSH 会话中运行。
使用你先前在 azd 输出中记下的 App Service 的值以及下面显示的模板,构建 SSH 会话的 URL,并在浏览器中导航到该 URL:
https://<app-name>.scm.azurewebsites.net/webssh/host
在 SSH 终端中运行
python3 src/fastapi_app/seed_data.py
。 如果该命令成功,则应用服务会成功连接到数据库。注意
只有对
/home
中文件的更改才能在应用重启之后持久保存。 不会保留/home
外部的更改。
5.浏览到应用
在 azd 输出中,找到应用的 URL 并在浏览器中导航到该 URL。 该 URL 在 AZD 输出中如下所示:
Deploying services (azd deploy) (✓) Done: Deploying service web - Endpoint: https://<app-name>.azurewebsites.net/
在列表中添加几家餐厅。
恭喜,你已在 Azure 应用服务中运行了一个 Web 应用,并安全连接到了 Azure Database for PostgreSQL。
6.流式传输诊断日志
Azure 应用服务可以捕获日志,以帮助你诊断应用程序的问题。 为方便起见,azd 模板已启用对本地文件系统的日志记录。
示例应用使用 Python 标准库日志模块来输出日志。 示例应用包括对记录器的调用,如下所示。
@app.get("/", response_class=HTMLResponse)
async def index(request: Request, session: Session = Depends(get_db_session)):
logger.info("root called")
statement = (
select(Restaurant, func.avg(Review.rating).label("avg_rating"), func.count(Review.id).label("review_count"))
.outerjoin(Review, Review.restaurant == Restaurant.id)
.group_by(Restaurant.id)
)
使用你先前在 azd 输出和下面显示的模板中记下的“订阅 ID”(Guid)、“资源组”和“应用服务”的值,构建用于流式传输应用服务日志的 URL,并在浏览器中导航到该 URL。
https://portal.azure.com/#@/resource/subscriptions/<subscription-guid>/resourceGroups/<group-name>/providers/Microsoft.Web/sites/<app-name>/logStream
事件可能需要几分钟才能显示在诊断日志中。 在为 Python 应用程序设置 Azure Monitor 系列文章中,详细了解 Python 应用中的日志记录。
7.清理资源
若要删除当前部署环境中的所有 Azure 资源,请运行 azd down
。
azd down
疑难解答
下面列出了尝试完成本教程时可能遇到的问题以及解决这些问题的步骤。
无法连接到 SSH 会话
如果你无法连接到 SSH 会话,则表示应用本身已启动失败。 请查看诊断日志了解详细信息。 例如,如果看到类似于 KeyError: 'AZURE_POSTGRESQL_CONNECTIONSTRING'
的错误,则可能表示缺少环境变量(你可能已删除应用设置)。
运行数据库迁移时出错
如果遇到与连接数据库相关的任何错误,请检查应用设置 (AZURE_POSTGRESQL_CONNECTIONSTRING
) 是否已更改。 如果没有该连接字符串,则 migrate 命令将无法与数据库通信。
常见问题
此设置花费有多大?
所创建资源的定价如下所示:
- 应用服务计划在基本层中创建,可以进行纵向扩展或缩减。 请参阅应用服务定价。
- PostgreSQL 灵活服务器是在最低可突发层 Standard_B1ms 中创建的,该层提供最小的存储大小,但可以纵向扩展或缩减。 请参阅 Azure Database for PostgreSQL 定价。
- 除非配置额外的功能(例如对等互连),否则虚拟网络不会产生费用。 请参阅 Azure 虚拟网络定价。
- 专用 DNS 区域会产生少量费用。 请参阅 Azure DNS 定价。
如何使用其他工具连接到在虚拟网络后面受保护的 PostgreSQL 服务器?
- 要从命令行工具进行基本访问,可以从应用的 SSH 终端运行
psql
。 - 若要从桌面工具进行连接,计算机必须位于虚拟网络中。 例如,它可以是连接到其中一个子网的 Azure VM,也可以是与 Azure 虚拟网络建立了站点到站点 VPN 连接的本地网络中的计算机。
- 还可以将 Azure Cloud Shell 与虚拟网络集成。
本地应用开发如何与 GitHub Actions 配合使用?
以应用服务中自动生成的工作流文件为例,每个 git push
都会启动新的生成和部署运行。 从 GitHub 存储库的本地克隆中,进行所需更新并推送到 GitHub。 例如:
git add .
git commit -m "<some-message>"
git push origin main
后续步骤
请继续学习下一教程,了解如何使用自定义域和证书保护应用。
了解应用服务如何运行 Python 应用: