本文介绍如何使用 GitHub Actions 中的持续集成和持续交付(CI/CD)平台将 Python Web 应用部署到 Linux 上的 Azure 应用服务。 GitHub Actions 工作流会自动生成代码,并在向存储库提交时将其部署到应用服务实例。 可以在 GitHub Actions 工作流中添加其他自动化,例如测试脚本、安全检查和多阶段部署。
为应用代码创建存储库
若要完成本文中的过程,需要提交到 GitHub 存储库的 Python Web 应用。
现有应用:若要使用现有的 Python Web 应用,请确保应用已提交到 GitHub 存储库。
新应用:如果需要新的 Python Web 应用,可以分叉和克隆 https://github.com/Microsoft/python-sample-vscode-flask-tutorial GitHub 存储库。 示例代码支持 Visual Studio Code 中的 Flask 教程,并提供正常运行的 Python 应用程序。
注释
如果应用使用 Django 和 SQLite 数据库,则它不适用于这些过程。 由于基于本地文件的存储限制,大多数云托管环境中不支持 SQLite。 请考虑切换到与云兼容的数据库,例如 PostgreSQL 或 Azure Cosmos DB。 有关详细信息,请参阅本文后面的 “查看 Django 注意事项 ”。
创建目标应用服务实例
创建应用服务实例的最快方法是通过交互式 Azure Cloud Shell 使用 Azure 命令行接口(CLI)。 Cloud Shell 包括 Git 和 Azure CLI。 在以下过程中,使用 az webapp up 命令创建应用服务实例并执行应用的初始部署。
通过 https://portal.azure.com 登录到 Azure 门户。
通过选择门户工具栏上的 Cloud Shell 选项打开 Azure CLI:
在 Cloud Shell 中,从下拉菜单中选择 Bash 选项:
在 Cloud Shell 中,使用命令 git clone 克隆存储库。
小窍门
若要将命令或文本粘贴到 Cloud Shell 中,请使用 Ctrl+Shift+V 键盘快捷方式,或右键单击并选择上下文菜单中的 “粘贴 ”。
对于 Flask 示例应用,可以使用以下命令。 将
<github-user>
部分替换为创建存储库分支的 GitHub 帐户的名称:git clone https://github.com/<github-user>/python-sample-vscode-flask-tutorial.git
如果应用位于其他存储库中,请为特定存储库设置 GitHub Actions。 将
<github-user>
部分替换为你创建存储库分支的 GitHub 帐户的名称,并在<repo-name>
占位符中提供实际的存储库名称:git clone https://github.com/<github-user>/<repo-name>.git
注释
Cloud Shell 由名为 cloud-shell-storage-your-region<> 的资源组中的 Azure 存储帐户提供支持。 该存储帐户包含 Cloud Shell 文件系统的映像,用于存储克隆的存储库。 此存储的成本很小。 完成本文后,可以删除存储帐户以及创建的其他资源。
在 Cloud Shell 中,将目录更改为 Python 应用的存储库文件夹,因此 az webapp up 命令会将应用识别为 Python。 对于 Flask 示例应用,请使用以下命令:
cd python-sample-vscode-flask-tutorial
在 Cloud Shell 中,使用 az webapp up 命令创建应用服务实例,并为应用执行初始部署:
az webapp up --name <app-service-name> --runtime "PYTHON:3.9"
<app-service-name>
对于占位符,请指定 Azure 中唯一的应用服务名称。 名称长度必须为 3-60 个字符,只能包含字母、数字和连字符。 名称必须以字母开头,并且必须以字母或数字结尾。有关系统上可用运行时的列表,请使用
az webapp list-runtimes
命令。在命令中输入运行时值时,请使用
PYTHON:X.Y
格式,即X.Y
Python 主版本和次要版本。还可以使用
--location
参数指定应用服务实例的区域位置。 若要获取可用位置的列表,请使用az account list-locations --output table
命令。
如果应用具有自定义启动脚本,请使用 az webapp config 命令启动脚本。
如果应用没有自定义启动脚本,请继续执行下一步。
对于 Flask 示例应用,需要运行以下命令来访问 startup.txt 文件中的启动脚本:
az webapp config set \ --resource-group <resource-group-name> \ --name <app-service-name> \ --startup-file startup.txt
请在
<resource-group-name>
和<app-service-name>
占位符中输入资源组名称和应用服务实例名称。 若要查找资源组名称,请检查上一az webapp up
命令的输出。 资源组名称包括 Azure 帐户名称,后跟 _rg 后缀,如 <azure-account-name>_rg所示。
若要查看正在运行的应用,请打开浏览器并转到应用服务实例的部署终结点。 在以下 URL 中,将
<app-service-name>
占位符替换为应用服务实例名称:http://<app-service-name>.azurewebsites.net
如果看到泛型页面,请等待几秒钟,让应用服务实例启动并刷新页面。
- 如果继续看到通用页面,请确认已从正确的文件夹部署。
- 对于 Flask 示例应用,请确认已从 python-sample-vscode-flask-tutorial 文件夹部署。 另请检查是否已正确设置启动命令。
在应用服务中设置持续部署
在下一过程中,设置持续交付(CD),这意味着每当工作流触发时,就会进行新的代码部署。 本文示例中的触发器是对存储库的主分支进行的任何更改,例如拉取请求 (PR)。
在 Cloud Shell 中,确认你位于系统的根目录中(
~
),而不是在应用子文件夹中,例如 python-sample-vscode-flask-tutorial。使用 az webapp deployment github-actions add 命令添加 GitHub Actions。 将任何占位符替换为你的特定值:
az webapp deployment github-actions add \ --repo "<github-user>/<github-repo>" \ --resource-group <resource-group-name> \ --branch <branch-name> \ --name <app-service-name> \ --login-with-github
该
--login-with-github
参数使用交互式方法检索个人访问令牌。 按照提示作并完成身份验证。如果系统遇到具有相同应用服务实例名称的现有工作流文件,请按照提示选择是否覆盖工作流。 可以将参数
--force
与命令一起使用,以自动覆盖任何冲突的工作流。
该
add
命令完成以下任务:- 在 存储库中的 .github/workflows/<workflow-name>.yml 路径处创建新的工作流文件。 文件名包含应用服务实例的名称。
- 为应用程序服务实例获取包含机密的发布配置文件,并将其添加为 GitHub Actions 机密。 机密的名称以 AZUREAPPSERVICE_PUBLISHPROFILE_开头。 此机密在工作流文件中引用。
使用 az webapp deployment source show 命令获取源代码管理部署配置的详细信息。 将占位符参数替换为你的特定值:
az webapp deployment source show \ --name <app-service-name> \ --resource-group <resource-group-name>
在命令输出中,确认
repoUrl
和branch
属性的值。 这些值应与使用命令指定的add
值匹配。
检查 GitHub 工作流和操作
工作流定义在存储库中 /.github/workflows/ 路径的 YAML (.yml) 文件中指定。 此 YAML 文件包含构成工作流的各种步骤和参数,这是与 GitHub 存储库关联的自动化过程。 可以使用工作流在 GitHub 上生成、测试、打包、发布和部署任何项目。
每个工作流由一个或多个作业组成,每个作业都是一组步骤。 每个步骤都是 shell 脚本或是一个操作。 每个作业在工作流文件中都有一个 Action 节。
对于使用 Python 代码设置的、用于部署到 Azure 应用服务的工作流,该工作流具有以下操作:
行动 | DESCRIPTION |
---|---|
结账 | 查看 运行器(GitHub Actions 代理)上的存储库。 |
setup-python | 在运行器上安装 Python。 |
appservice-build | 构建 Web 应用。 |
webapps-deploy | 使用发布配置文件凭据在 Azure 中进行身份验证来部署 Web 应用。 凭据存储在 GitHub 机密中。 |
用于创建工作流的工作流模板是 Azure/actions-workflow-samples。
工作流在将事件推送到指定的分支时触发。 事件和分支在工作流文件的开头定义。 例如,以下代码片段显示工作流是在将事件推送到 主 分支时触发的:
on:
push:
branches:
- main
OAuth 授权的应用
设置持续部署时,可将 Azure 应用服务授权为 GitHub 帐户的授权 OAuth 应用。 应用服务使用授权访问在存储库的 .github/workflows/<workflow-name>.yml 路径创建一个 GitHub Action 的 YAML 文件。
若要查看授权的应用并在 GitHub 帐户下撤销权限,请转到“设置集成/应用程序”>:
工作流发布配置文件机密
在添加到存储库的 .github/workflows/<workflow-name>.yml 工作流文件中,有一个占位符,用于发布工作流部署作业所需的配置文件凭据。 发布配置文件信息以加密形式存储在存储库中。
若要查看机密,请转到 “设置>安全>机密”和“变量>作”:
在本文中,GitHub 操作使用发布配置文件凭据进行身份验证。 可通过其他方法进行身份验证,例如使用服务主体或 OpenID Connect。 有关详细信息,请参阅 使用 GitHub Actions 部署到应用服务。
运行和测试工作流
最后一步是通过更改存储库来测试工作流。
在浏览器中,转到示例存储库(或使用的存储库),然后选择你之前设置为触发器一部分的分支:
对 Python Web 应用进行少量更改。
对于 Flask 教程,以下是简单的更改:
- 转到触发器分支的 /hello-app/templates/home.html 文件。
- 选择 “编辑 ”(铅笔)。
- 在编辑器中,找到 print
<p>
语句,并添加文本“重新部署!”
将更改直接提交到你正在工作的分支。
- 在编辑器中,选择右上角的 “提交更改 ”。 “ 提交更改 ”窗口随即打开。
- 在 “提交更改 ”窗口中,根据需要修改提交消息,然后选择“ 提交更改”。
提交过程会触发 GitHub Actions 工作流。
还可以手动触发工作流:
转到为持续部署设置的存储库的“操作”选项卡。
在工作流列表中选择工作流,然后选择“ 运行工作流”。
排查工作流故障
可以在应用存储库的 “作 ”选项卡上检查工作流的状态。 检查本文中创建的工作流文件时,会看到两个作业: 生成 和 部署。 提醒一下,工作流基于 Azure/actions-workflow-samples 模板。
对于失败的作业,请查看作业任务的输出以确定失败原因。
下面是一些要调查的常见问题:
如果应用由于缺少依赖项而失败,则部署期间未处理 requirements.txt 文件。 如果直接在门户上创建了 Web 应用,而不是使用
az webapp up
本文中所示的命令,则会发生此行为。如果通过门户配置了应用服务,则生成操作
SCM_DO_BUILD_DURING_DEPLOYMENT
设置可能未被设置。 此设置必须设置为true
。 该az webapp up
命令会自动设置生成操作。如果看到有关“TLS 握手超时”的错误消息,请在应用存储库的“操作”选项卡下选择“触发自动部署”手动运行工作流。 可以确定超时是否是临时问题。
如果为容器应用设置持续部署,如本文所示,则会自动为你创建初始工作流文件 .github/workflows/<workflow-name>.yml 。 如果修改了该文件,请删除修改,以查看它们是否导致失败。
运行部署后脚本
部署后脚本可以完成多个任务,例如定义应用代码预期的环境变量。 将脚本添加为应用代码的一部分,并使用启动命令执行脚本。
若要避免在工作流 YAML 文件中对变量值进行硬编码,请考虑在 GitHub 中配置变量并引用脚本中的变量名称。 可以为存储库或环境(帐户存储库)创建加密机密。 有关详细信息,请参阅 在 GitHub Actions 中使用机密。
查看 Django 注意事项
如本文前面所述,如果使用单独的数据库,可以使用 GitHub Actions 将 Django 应用部署到 Linux 上的 Azure 应用服务。 无法使用 SQLite 数据库,因为应用服务会锁定 db.sqlite3 文件,这会阻止读取和写入。 此行为不会影响外部数据库。
在 应用服务上配置 Python 应用 - 容器启动过程 文章介绍了应用服务如何在应用代码中自动查找 wsgi.py 文件(通常包含应用对象)。 使用 webapp config set
命令设置启动命令时,使用 --startup-file
参数指定包含应用对象的文件。 该 webapp config set
命令在 webapps-deploy作中不可用。 相反,可以使用 startup-command
参数来指定启动命令。 例如,以下代码演示如何在工作流文件中指定启动命令:
startup-command: startup.txt
使用 Django 时,通常希望在部署应用代码后使用 python manage.py migrate
命令迁移数据模型。 可以在部署后脚本中运行 migrate 命令。
断开 GitHub Actions 的连接
通过断开 GitHub Actions 与应用服务实例的连接,可以重新配置应用部署。 可以在断开连接后选择工作流文件会发生什么情况,以及是否保存或删除该文件。
- Azure CLI
- Azure 门户
使用以下 Azure CLI 命令 az webapp deployment github-actions remove 断开 GitHub Actions 的连接。 将任何占位符替换为特定值:
az webapp deployment github-actions remove \
--repo "<github-username>/<github-repo>" \
--resource-group <resource-group-name> \
--branch <branch-name> \
--name <app-service-name> \
--login-with-github
清理资源
若要避免对本文中创建的 Azure 资源产生费用,请删除包含应用服务实例和应用服务计划的资源组。
- Azure CLI
- Azure 门户
在安装 Azure CLI(包括 Azure Cloud Shell)的任何位置,都可以使用 az group delete 命令删除资源组:
az group delete --name <resource-group-name>
删除存储帐户
若要删除维护 Cloud Shell 文件系统的存储帐户(每月会产生少量费用),请删除以 cloud-shell-storage 开头的资源组。 如果你是组的唯一用户,则删除资源组是安全的。 如果有其他用户,则可以删除资源组中的存储帐户。
更新 GitHub 帐户和存储库
如果删除 Azure 资源组,请考虑对已连接进行持续部署的 GitHub 帐户和存储库进行以下修改:
- 在应用存储库中,删除 .github/workflows/<workflow-name>.yml 文件。
- 在应用存储库设置中,删除为工作流创建的 AZUREAPPSERVICE_PUBLISHPROFILE_ 密钥。
- 在 GitHub 帐户设置中,删除 Azure 应用服务作为 GitHub 帐户的授权 Oauth 应用。