在 Azure 中部署使用 PostgreSQL 的 Python(Django 或 Flask)Web 应用
在本教程中,你要将一个使用 Azure Database for PostgreSQL 关系数据库服务的数据驱动 Python Web 应用(Django 或 Flask)部署到 Azure 应用服务。 Azure 应用服务支持 Linux 服务器环境中的 Python。
若要完成本教程,你需要:
- 具有活动订阅的 Azure 帐户。 如果没有 Azure 帐户,可创建一个试用帐户。
- 了解使用 Flask 的 Python 开发或使用 Django 的 Python 开发
- 具有活动订阅的 Azure 帐户。 如果没有 Azure 帐户,可创建一个试用帐户。
- 已安装 Azure 开发人员 CLI。 可以使用 Azure Cloud Shell 执行这些步骤,因为它已安装 Azure 开发人员 CLI。
跳到末尾
安装 Azure 开发人员 CLI 后,可以部署本教程所示的完全配置的示例应用,并查看它在 Azure 中的运行情况。 只需在空的工作目录中运行以下命令:
azd auth login
azd init --template msdocs-flask-postgresql-sample-app
azd up
示例应用程序
我们提供了使用 Flask 和 Django 框架的示例 Python 应用程序来帮助你学习本教程。 若要部署这些应用程序但不在本地运行它们,请跳过本部分。
若要在本地运行应用程序,请确保在本地安装 Python 3.7 或更高版本和 PostgreSQL。 然后克隆示例存储库的 starter-no-infra
分支,并更改为存储库根路径。
git clone -b starter-no-infra https://github.com/Azure-Samples/msdocs-flask-postgresql-sample-app
cd msdocs-flask-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
安装依赖项:
pip install -r requirements.txt
使用以下命令运行示例应用程序:
# Run database migration
flask db upgrade
# Run the app at http://127.0.0.1:5000
flask run
1. 创建应用服务和 PostgreSQL
此步骤创建 Azure 资源。 本教程中使用的步骤创建一组默认安全的资源,其中包括应用服务和 Azure Database for PostgreSQL。 此创建过程中,你将指定:
- Web 应用的名称。 此名称用作 Web 应用的 DNS 名称的一部分,其格式为
https://<app-name>.chinacloudsites.cn
。 - “区域”,在世界上以物理方式运行应用。
- 应用的运行时堆栈。 在此处选择要用于应用的 Python 版本。
- 应用的托管计划。 它是定价层,包括应用的一组功能和缩放容量。
- 应用的资源组。 使用资源组可将应用程序所需的所有 Azure 资源分组到一个逻辑容器中。
登录到 Azure 门户并按照以下步骤创建 Azure 应用服务资源。
步骤 1:在 Azure 门户中:
- 在 Azure 门户顶部的搜索栏中,输入“Web 应用数据库”。
- 选择“市场”标题下标记为“Web 应用 + 数据库”的项目。 还可以直接导航到创建向导。
步骤 2:在“创建 Web 应用 + 数据库”页上,按下面所述填写表单。
- 资源组 → 选择“新建”,然后使用名称 msdocs-python-postgres-tutorial。
- 区域 → 与你靠近的任何 Azure 区域。
- 名称 → msdocs-python-postgres-XYZ,其中 XYZ 是任意三个随机字符。 该名称在 Azure 中必须唯一。
- 运行时堆栈 → Python 3.10。
- 数据库 → 默认已选择“PostgreSQL 灵活服务器”作为数据库引擎。 默认情况下,服务器名称和数据库名称也会设置为适当的值。
- 托管计划 → 基本。 准备就绪后,可以稍后纵向扩展到生产定价层。
- 选择“查看 + 创建”。
- 验证完成后,选择“创建”。
步骤 3:该部署需要数分钟才能完成。 部署完成后,选择“转到资源”按钮。 这将直接转到应用服务应用,但会创建以下资源:
- 资源组 → 所有已创建资源的容器。
- 应用服务计划 → 定义应用服务的计算资源。 将创建基本层中的 Linux 计划。
- 应用服务 → 表示应用,且在应用服务计划中运行。
- 虚拟网络 → 与应用服务应用集成,并隔离后端网络流量。
- Azure Database for PostgreSQL 灵活服务器 → 只能从虚拟网络内部访问。 你的数据库和用户创建于此服务器上。
- 专用 DNS 区域 → 在虚拟网络中启用 PostgreSQL 服务器的 DNS 解析。
2. 验证连接设置
创建向导已经为你生成了连接变量作为应用设置。 使用应用设置可以将连接机密保留在代码存储库之外。 准备好将机密移动到更安全的位置后,下面提供了一篇有关在 Azure 密钥保管库中存储的文章。
步骤 1:在左侧菜单的“应用服务”页面中,选择“配置”。
步骤 2:在“配置”页的“应用程序设置”选项卡中,验证 AZURE_POSTGRESQL_CONNECTIONSTRING
是否存在。 它将作为环境变量注入到运行时环境中。
步骤 3:在终端或命令提示符下,运行以下 Python 脚本来生成唯一机密:python -c 'import secrets; print(secrets.token_hex())'
。 复制输出值以在下一步中使用。
3. 部署示例代码
在此步骤中,你将使用 GitHub Actions 配置 GitHub 部署。 这只是部署到应用服务的许多方法之一,也是一种在部署过程中持续集成的好方法。 默认情况下,GitHub 存储库的每个 git push
都会启动生成和部署操作。
步骤 1:在新浏览器窗口中:
- 登录到 GitHub 帐户。
- 导航到 https://github.com/Azure-Samples/msdocs-flask-postgresql-sample-app。
- 选择“Fork”。
- 选择“创建分支”。
步骤 2:在 GitHub 页中,按 .
键在浏览器中打开 Visual Studio Code。
步骤 3:在浏览器上的 Visual Studio Code 中,在资源管理器中打开“azureproject/production.py”。 查看生产环境中使用的环境变量,包括在配置页中看到的应用设置。
步骤 4:返回“应用服务”页,在左侧菜单中,选择“部署中心”。
步骤 5:在“部署中心”页中:
- 在“源”中,选择“GitHub”。 默认情况下,选择 GitHub Actions 作为生成提供程序。
- 登录到 GitHub 帐户,并按照提示授权 Azure。
- 在“组织”中,选择你的帐户。
- 在“存储库”中,选择“msdocs-flask-postgresql-sample-app”。
- 在“分支”中,选择“主”。
- 保留所选的默认选项以添加工作流。
- 在“身份验证类型”下,选择“用户分配的标识”。
- 在顶部菜单中,选择“保存”。 应用服务会将工作流文件提交到所选 GitHub 存储库中(在
.github/workflows
目录中)。
步骤 6:在“部署中心”页中:
- 选择“日志”。 部署运行已启动。
- 在部署运行的日志项中,选择“生成/部署日志”。
步骤 7:你已转到 GitHub 存储库,并看到 GitHub Action 正在运行。 工作流文件定义两个单独的阶段,即生成和部署阶段。 等待 GitHub 运行以显示“完成”状态。 此过程大约需要 5 分钟。
遇到问题? 查看故障排除指南。
4. 生成数据库架构
在 PostgreSQL 数据库受虚拟网络保护的情况下,运行 Flask 数据库迁移的最简单方法是使用应用服务容器在 SSH 会话中运行。
步骤 1:返回“应用服务”页,在左侧菜单中,
- 选择“SSH”。
- 选择“转到”。
步骤 2:在 SSH 终端中运行 flask db upgrade
。 如果该命令成功,则应用服务会成功连接到数据库。
只有对 /home
中文件的更改才能在应用重启之后持久保存。 不会保留 /home
外部的更改。
5.浏览到应用
步骤 1:在“应用服务”页中:
- 从左侧菜单中选择“概述”。
- 选择应用的 URL。 你也可以直接导航到
https://<app-name>.chinacloudsites.cn
。
步骤 2:在列表中添加几家餐厅。 恭喜,你已在 Azure 应用服务中运行了一个 Web 应用,并安全连接到了 Azure Database for PostgreSQL。
6.流式传输诊断日志
Azure 应用服务会捕获输出到控制台的所有消息,以帮助你诊断应用程序的问题。 示例应用包含了 print()
语句用于演示此功能,如下所示。
@app.route('/', methods=['GET'])
def index():
print('Request for index page received')
restaurants = Restaurant.query.all()
return render_template('index.html', restaurants=restaurants)
步骤 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-flask-postgresql-sample-app cd msdocs-flask-postgresql-sample-app
此克隆分支是你的起点。 它包含简单的数据驱动 Flask 应用程序。
从存储库根路径,运行
azd init
。azd init --template python-app-service-postgresql-infra
出现提示时,请提供以下答案:
问题 Answer 当前目录不为空。 是否要在此处初始化“<your-directory>”中的项目? Y 你希望对这些文件执行哪些操作? 使现有文件保持不变 输入新环境名称 键入唯一名称。 azd 模板将此名称用作 Azure 中 Web 应用的 DNS 名称的一部分 ( <app-name>.chinacloudsites.cn
)。 允许使用字母数字字符和下划线。运行
azd up
命令以提供必要的 Azure 资源并部署应用代码。 如果尚未登录到 Azure,浏览器将启动并要求你登录。azd up
命令还将提示选择要部署到的所需订阅和位置。azd up
azd up
命令可能需要几分钟时间才能完成。 它还会编译和部署应用程序代码,但你稍后将修改代码以使用应用服务。 在运行时,该命令会提供有关预配和部署过程的消息,包括指向 Azure 中部署的链接。 完成后,命令还会显示指向部署应用程序的链接。此 azd 模板包含使用以下 Azure 资源生成安全默认体系结构的文件(azure.yaml 和 infra 目录):
2.使用数据库连接字符串
你使用的 azd 模板已为你生成了连接变量作为应用设置,并将它们输出到终端,以方便你使用。 使用应用设置可以将连接机密保留在代码存储库之外。
在 azd 输出中,找到应用设置并查找设置
AZURE_POSTGRESQL_CONNECTIONSTRING
和AZURE_REDIS_CONNECTIONSTRING
。 为保护机密安全,只会显示设置名称。 它们在 azd 输出中如下所示:App Service app has the following settings: - AZURE_POSTGRESQL_CONNECTIONSTRING - AZURE_REDIS_CONNECTIONSTRING - FLASK_DEBUG - SCM_DO_BUILD_DURING_DEPLOYMENT - SECRET_KEY
AZURE_POSTGRESQL_CONNECTIONSTRING
包含 Azure 中 Postgres 数据库的连接字符串,AZURE_REDIS_CONNECTIONSTRING
则包含 Azure 中 Redis 缓存的连接字符串。 需要使用代码连接到它。 打开 azureproject/production.py,取消注释以下行,并保存文件:conn_str = os.environ['AZURE_POSTGRESQL_CONNECTIONSTRING'] conn_str_params = {pair.split('=')[0]: pair.split('=')[1] for pair in conn_str.split(' ')} DATABASE_URI = 'postgresql+psycopg2://{dbuser}:{dbpass}@{dbhost}/{dbname}'.format( dbuser=conn_str_params['user'], dbpass=conn_str_params['password'], dbhost=conn_str_params['host'], dbname=conn_str_params['dbname'] )
应用程序代码现已配置为连接到 Azure 中的 PostgreSQL 数据库。 如果需要,请打开
app.py
并查看如何使用DATABASE_URI
环境变量。在终端中运行
azd deploy
。azd deploy
4. 生成数据库架构
在 PostgreSQL 数据库受虚拟网络保护的情况下,运行 Flask 数据库迁移的最简单方法是使用应用服务容器在 SSH 会话中运行。
在 azd 输出中,找到 SSH 会话的 URL,并在浏览器中导航到该 URL。 它在输出中如下所示:
Open SSH session to App Service container at: https://<app-name>.scm.chinacloudsites.cn/webssh/host
在 SSH 终端中运行
flask db upgrade
。 如果该命令成功,则应用服务会成功连接到数据库。注意
只有对
/home
中文件的更改才能在应用重启之后持久保存。 不会保留/home
外部的更改。
5.浏览到应用
在 azd 输出中,找到应用的 URL 并在浏览器中导航到该 URL。 该 URL 在 AZD 输出中如下所示:
Deploying services (azd deploy) (✓) Done: Deploying service web - Endpoint: https://<app-name>.chinacloudsites.cn/
在列表中添加几家餐厅。
恭喜,你已在 Azure 应用服务中运行了一个 Web 应用,并安全连接到了 Azure Database for PostgreSQL。
6.流式传输诊断日志
Azure 应用服务可以捕获控制台日志,以帮助你诊断应用程序的问题。 为方便起见,azd 模板已启用对本地文件系统的日志记录以及将日志传送到 Log Analytics 工作区。
示例应用包含了 print()
语句用于演示此功能,如以下代码片段所示。
@app.route('/', methods=['GET'])
def index():
print('Request for index page received')
restaurants = Restaurant.query.all()
return render_template('index.html', restaurants=restaurants)
在 azd 输出中,找到流式传输应用服务日志的链接,并在浏览器中导航到该链接。 该链接在 azd 输出中如下所示:
Stream App Service logs at: https://portal.azure.cn/#@/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 服务器?
- 本地应用开发如何处理 GitHub Actions?
- 如何将 Django 示例配置为在 Azure 应用服务上运行?
此设置花费有多大?
所创建资源的定价如下所示:
- 应用服务计划在基本层中创建,可以进行纵向扩展或缩减。 请参阅应用服务定价。
- PostgreSQL 灵活服务器是在最低可突发层 Standard_B1ms 中创建的,该层提供最小的存储大小,但可以纵向扩展或缩减。 请参阅 Azure Database for PostgreSQL 定价。
- 除非配置额外的功能(例如对等互连),否则虚拟网络不会产生费用。 请参阅 Azure 虚拟网络定价。
- 专用 DNS 区域会产生少量费用。 请参阅 Azure DNS 定价。
如何使用其他工具连接到在虚拟网络后面受保护的 PostgreSQL 服务器?
- 要从命令行工具进行基本访问,可以从应用的 SSH 终端运行
psql
。 - 若要从桌面工具进行连接,计算机必须位于虚拟网络中。 例如,它可以是连接到其中一个子网的 Azure VM,也可以是与 Azure 虚拟网络建立了站点到站点 VPN 连接的本地网络中的计算机。
本地应用开发如何与 GitHub Actions 配合使用?
以应用服务中自动生成的工作流文件为例,每个 git push
都会启动新的生成和部署运行。 从 GitHub 存储库的本地克隆中,进行所需更新并推送到 GitHub。 例如:
git add .
git commit -m "<some-message>"
git push origin main
如何将 Django 示例配置为在 Azure 应用服务上运行?
Django 示例应用程序在 azureproject/production.py 文件中配置设置,使它可以在 Azure 应用服务中运行。 将 Django 部署到生产环境时经常会做出这些更改,它们并非特定于应用服务。
- Django 验证传入请求中的 HTTP_HOST 标头。 示例代码使用应用服务中的
WEBSITE_HOSTNAME
环境变量将应用的域名添加到 Django 的 ALLOWED_HOSTS 设置。
# Configure the domain name using the environment variable
# that Azure automatically creates for us.
ALLOWED_HOSTS = [os.environ['WEBSITE_HOSTNAME']] if 'WEBSITE_HOSTNAME' in os.environ else []
- Django 不支持在生产中提供静态文件。 对于本教程,请使用 WhiteNoise 来支持提供文件。 WhiteNoise 包已与 requirements.txt 一起安装,其中间件已添加到列表中。
# WhiteNoise configuration
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
# Add whitenoise middleware after the security middleware
'whitenoise.middleware.WhiteNoiseMiddleware',
然后根据 Django 文档配置静态文件设置。
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
有关详细信息,请参阅 Django 应用的生产设置。
后续步骤
请继续学习下一教程,了解如何使用自定义域和证书保护应用。
了解应用服务如何运行 Python 应用: