使用 Azure Pipelines 生成 Python Web 应用并将其部署到 Azure 应用服务

Azure DevOps Services

本教程介绍如何使用 Azure Pipelines 进行持续集成和持续交付(CI/CD),以生成 Python Web 应用并将其部署到 Linux 上的 Azure 应用服务。 每当应用代码存储库提交内容时,管道都会自动生成 Python Web 应用并将其部署到应用服务。

在本教程中,你将:

  • 创建 Python Web 应用并将其上传到 Azure 应用服务。
  • 将 Azure DevOps 项目连接到 Azure。
  • 为应用创建特定于 Azure Pipelines Python 的生成和部署管道。
  • 运行管道以生成、测试和部署到 Azure 应用服务 Web 应用。
  • 设置触发器以在提交到存储库时运行管道。

若要详细了解 Azure Pipelines 概念,请观看以下视频:

先决条件

产品 要求
Azure DevOps - 一个 Azure DevOps 项目
- 能够在 Microsoft 托管的代理上运行管道。 可以购买并行作业,也可以请求免费层。
- 对 YAML 和 Azure Pipelines 的基本知识。 有关详细信息,请参阅创建第一个管道
- 权限:
     - 若要创建管道:必须位于 “参与者 ”组中,并且该组需要将 “创建生成管道 ”权限设置为“允许”。 项目管理员组的成员可以管理管道。
    - 若要创建服务连接:必须具有服务连接的管理员创建者角色。
GitHub - GitHub 帐户。
- 用于授权 Azure Pipelines 的 GitHub 服务连接
天蓝色 一个 Azure 订阅
产品 要求
Azure DevOps - 一个 Azure DevOps 项目
- 自托管代理。 若要创建一个代理,请参阅自托管代理
- 对 YAML 和 Azure Pipelines 的基本知识。 有关详细信息,请参阅创建第一个管道
- 权限:
    - 若要创建管道:必须位于 “参与者 ”组中,并且该组需要将 “创建生成管道 ”权限设置为“允许”。 项目管理员组的成员可以管理管道。
    - 若要创建服务连接:必须具有服务连接的管理员创建者角色。
GitHub - GitHub 帐户。
- 用于授权 Azure Pipelines 的 GitHub 服务连接
天蓝色 一个 Azure 订阅

配置自托管代理

自承载生成代理不支持下载 Python 版本。 若要使用自己的自承载代理,需要将代理配置为运行 Python。

为了避免兼容性问题,请将 Python 版本与 Azure 应用服务 Web 应用中的运行时版本匹配, 3.11 在本例中。 必须预安装 Python 版本。 使用完整的安装程序来获取与 pip 兼容的 Python 版本。

需要将所需的 Python 版本添加到自承载代理上的工具缓存中,以便管道任务可以使用它。 通常,工具缓存位于代理的 _work/_tool 目录中。 或者,可以使用环境变量 AGENT_TOOLSDIRECTORY替代路径。 在工具目录下,基于 Python 版本创建以下目录结构:

$AGENT_TOOLSDIRECTORY/
    Python/
        {version number}/
            {platform}/
                {tool files}
            {platform}.complete

版本号应遵循 1.2.3 格式。 平台应为 x86 或 x64。 工具文件应为解压缩的 Python 版本文件。 {platform}.complete 应为一个 0 字节文件,它类似 x86.completex64.complete 且仅表示该工具已正确安装在缓存中。

例如,若要在 64 位 Windows 计算机上使用 Python 3.11,请创建以下目录结构:

$AGENT_TOOLSDIRECTORY/
    Python/
        3.11.4/
            x64/
                {python files}
            x64.complete

如果托管代理的计算机已有要使用的 Python 版本,则可以将文件复制到工具缓存。 如果没有该 Python 版本,则可从 Python 网站下载它。

准备示例应用

  1. https://github.com/Microsoft/python-sample-vscode-flask-tutorial 对 GitHub 帐户创建示例存储库分支。

  2. 使用 git clone <your-forked-repository-url>.git.. 将分支克隆到本地计算机。

  3. 使用 cd python-sample-vscode-flask-tutorial本地克隆并在本地生成并运行应用,以确保它正常工作。

    python -m venv .env
    source .env/Scripts/activate
    pip install --upgrade pip
    pip install -r ./requirements.txt
    export FLASK_APP=hello_app.webapp
    flask run
    
  4. 若要测试应用,请转到 http://localhost:5000 浏览器窗口中,并验证是否看到 标题 Visual Studio Flask 教程

  5. 关闭浏览器窗口,并使用 Ctrl+C 停止 Flask 服务器。

创建和部署应用服务 Web 应用

在 Azure 门户中使用 Cloud Shell 创建 Azure 应用服务 Web 应用。 若要使用 Cloud Shell,请登录到 Azure 门户 ,然后选择工具栏上的 Cloud Shell 按钮。

Azure 门户工具栏上的“Azure Cloud Shell”按钮的屏幕截图。

Cloud Shell 显示在浏览器底部。 请确保在下拉菜单中选择 Bash 作为环境。 你可以将 Cloud Shell 窗口最大化,以给自己更多的空间。

Azure Cloud Shell 的屏幕截图。

提示

若要粘贴到 Cloud Shell 中,请使用 Ctrl+Shift+V 或右键单击,然后从上下文菜单中选择“ 粘贴 ”。

创建和部署 Web 应用

  1. 在 Cloud Shell 中,使用以下命令将分叉存储库克隆到 Azure,并替换为 <your-forked-repository-url> 分叉存储库的 URL。

    git clone <your-forked-repository-url>
    
  2. 将目录更改为克隆的存储库文件夹。

    cd python-sample-vscode-flask-tutorial
    
  3. 运行 az webapp up 命令来预配应用服务 Web 应用并执行第一个部署。 使用 --name <your-web-app-name> 参数来分配在 Azure 中唯一的名称,例如个人或公司名称以及应用标识符,例如 --name <your-name>-flaskpipelines。 在没有参数的情况下运行 az webapp up 会分配一个在 Azure 中唯一的随机生成的 Web 应用名称。

    az webapp up --name <your-web-app-name>
    

az webapp up 命令将应用识别为 Python 应用,并执行以下作:

  1. 创建默认 资源组
  2. 创建默认 应用服务计划
  3. 创建具有分配名称的 Web 应用。 应用 URL<your-web-app-name>.azurewebsites.net.
  4. 当前工作目录中的所有文件部署到 ZIP 存档,并启用生成自动化。
  5. .azure/config 文件中本地缓存参数,以便在使用或其他az webapp up命令从项目文件夹az webapp进行部署时,无需再次指定参数。 默认情况下,这些命令使用缓存的值。

可以使用命令参数将默认作替换为自己的值。 有关详细信息,请参阅 az webapp up

az webapp up 命令为示例 Web 应用生成以下 JSON 输出:

{
  "URL": <your-web-app-url>,
  "appserviceplan": <your-app-service-plan-name>,
  "location": <your-azure-region>,
  "name": <your-web-app-name>,
  "os": "Linux",
  "resourcegroup": <your-resource-group>,
  "runtime_version": "python|3.11",
  "runtime_version_detected": "-",
  "sku": <sku>,
  "src_path": <repository-source-path>
}

URL记录本教程稍后要使用的值resourcegroupruntime_version值。

设置启动命令

python-sample-vscode-flask-tutorial 应用有一个 startup.txt 文件,其中包含针对该 Web 应用的特定启动命令。 使用资源组和 Web 应用名称输入以下命令,将 Web 应用 startup-file 配置属性设置为 startup.txt

az webapp config set --resource-group <your-resource-group> --name <your-web-app-name> --startup-file startup.txt

命令完成后,JSON 输出会显示 Web 应用的所有配置设置。

要查看正在运行的应用,请打开浏览器并转到命令输出中显示的 URLaz webapp up。 如果看到一个通用页面,则请等待几秒钟以便应用服务启动,然后刷新此页面。 验证是否看到 标题 Visual Studio Flask 教程

将 Azure DevOps 项目连接到 Azure 订阅

若要使用 Azure Pipelines 部署到 Azure 应用服务 Web 应用,需要将 Azure DevOps 项目连接到 Azure 资源。

创建服务主体

服务主体是为应用程序、托管服务和自动化工具创建的标识,用于访问 Azure 资源。 此访问权限仅限于分配给服务主体的角色,从而可以控制可在哪个级别访问哪些资源。

若要创建服务主体,请在 Bash Cloud Shell 中运行以下命令。 替换为 <service-principal-name> 服务主体的名称、 <your-subscription-id> Azure 订阅 ID 以及 <your-resource-group> Web 应用的资源组。

az ad sp create-for-rbac --display-name <service-principal-name> --role contributor --scopes /subscriptions/<your-subscription-id>/resourceGroups/<your-resource-group>

该命令返回以下 JSON 对象:

{
  "appId": "<client GUID>",
  "displayName": "<service-principal-name">,
  "password": "<password-string>",
  "tenant": "<tenant GUID>"
  ...
}

记下用于在下一部分中创建服务连接的值appIdpasswordtenantId值。

创建服务连接

服务连接提供从 Azure Pipelines 到外部和远程服务的经过身份验证的访问。 若要部署到 Azure 应用服务 Web 应用,请为 Web 应用创建与资源组的服务连接。

  1. 在 Azure DevOps 项目页上,选择 “项目设置”。

  2. “项目设置”中,选择 “管道>服务连接”。

  3. “服务连接 ”页上,如果此服务连接是项目中的第一个连接,请选择“ 新建服务连接 ”或 “创建服务连接 ”。

    在项目设置中选择管道服务连接的屏幕截图。

  4. “新建服务连接 ”屏幕上,选择 “Azure 资源管理器 ”,然后选择“ 下一步”。

    Azure 资源管理器服务连接选择的屏幕截图。

  5. “新建 Azure 服务连接 ”屏幕上,选择 标识类型。 此示例使用建议的应用注册(自动)。 有关身份验证方法的详细信息,请参阅使用 Azure 资源管理器服务连接以连接到 Azure

  6. 对于凭据,请选择“工作负荷标识联合”(自动)。

  7. 填写以下字段:

    • 范围级别:选择 订阅
    • 订阅:选择 Azure 订阅。
    • 资源组:选择包含 Web 应用的资源组。
    • 服务连接名称:输入连接的描述性名称。
    • 向所有管道授予访问权限:选中此复选框可授予对项目中所有管道的访问权限。
  8. 选择保存

    “新建 Azure 服务连接”对话框的屏幕截图。

  1. 在 Azure DevOps 项目页上,选择 “项目设置”。

  2. “项目设置”中,选择 “管道>服务连接”。

  3. “服务连接 ”页上,如果此服务连接是项目中的第一个连接,请选择“ 新建服务连接 ”或 “创建服务连接 ”。

    项目仪表板上“项目设置”按钮的屏幕截图。

  4. “新建服务连接 ”屏幕上,选择 “Azure 资源管理器 ”,然后选择“ 下一步”。

    显示 Azure 资源管理器选择的屏幕截图。

  5. 选择 “服务主体”(手动), 然后选择“ 下一步”。

    显示选择服务主体身份验证方法(手动)的屏幕截图。

  6. “新建 Azure 服务连接 ”屏幕上,完成以下字段:

    • 环境:选择 Azure 云
    • 范围级别:选择 订阅
    • 订阅 ID:输入 Azure 订阅 ID。
    • 订阅名称:输入 Azure 订阅名称。
  7. “身份验证 ”部分中,完成以下字段:

    • 服务主体 ID:输入 appId 命令返回 az ad sp create-for-rbac 的值。
    • 凭据:选择 服务主体密钥
    • 服务主体密钥:输入 password 命令返回 az ad sp create-for-rbac 的值。
    • 租户 ID:输入 tenant 命令返回 az ad sp create-for-rbac 的值。
    • 选择验证以验证此连接。
  8. 在“ 详细信息 ”部分的 “服务连接名称”下,输入服务连接的名称。

  9. 选中复选框,以 授予对所有管道的访问权限

  10. 选择验证并保存

    新服务连接屏幕顶部的屏幕截图。

连接将显示在“服务连接 ”列表中,并已准备好在管道中使用。

创建管道

创建管道以生成 Python Web 应用并将其部署到 Azure 应用服务。

  1. 在项目的左侧导航菜单上,选择 “管道”。

  2. “管道 ”页上,选择“ 新建管道”,如果此管道是项目中的第一个管道,则 选择“创建管道 ”。

    管道列表中的“新建管道”按钮的屏幕截图。

  3. 代码屏幕的“位置” 上,选择 “GitHub”。 系统可能会提示你登录 GitHub。

    选择 GitHub 作为代码位置的屏幕截图。

  4. “选择存储库 ”屏幕上,选择分叉示例存储库。 GitHub 可能会提示你再次输入 GitHub 密码,或安装 Azure Pipelines GitHub 应用。 按照屏幕上的说明安装应用。 有关详细信息,请参阅 GitHub 应用身份验证

    存储库选择的屏幕截图。

  5. “配置管道 ”页上,选择 Python 到 Azure 上的 Linux Web 应用

  6. 在下一个屏幕上,选择 Azure 订阅,然后选择 “继续”。

  7. 在下一个屏幕上,选择 Azure Web 应用,然后选择 “验证并配置”。

Azure Pipelines 创建一个 azure-pipelines.yml 文件,并将其显示在 YAML 管道编辑器中。

  1. 在项目的左侧导航菜单上,选择 “管道”。

  2. “管道 ”页上,选择“ 新建管道”,如果此管道是项目中的第一个管道,则 选择“创建管道 ”。

    管道列表中的“新建管道”按钮的屏幕截图。

  3. 代码页的“位置” 上,选择 “GitHub Enterprise Server”。 系统可能会提示你登录 GitHub。

    选择 GitHub 以作为代码位置的屏幕截图。

  4. “选择存储库 ”选项卡上,选择分支示例存储库。 GitHub 可能会提示你再次输入 GitHub 密码,或安装 Azure Pipelines GitHub 扩展或应用。 按照屏幕上的说明安装应用。 有关详细信息,请参阅访问 GitHub 存储库

    存储库选择的屏幕截图。

  5. “配置管道 ”页上,选择 “初学者管道”。

  6. “查看管道 YAML ”页上,将初学者 azure-pipelines.yml 文件的内容替换为以下 YAML 管道文件。 在 YAML 文件中:

    • <your-service-connection-name><your-web-app-name> 占位符替换为你自己的值。

    • 替换为 <your-pool-name> 要使用的代理池的名称,并替换为 <your-python-version> 代理上运行的 Python 版本。 此版本应与命令的 runtime_version JSON 输出匹配az webapp up

YAML 管道文件

“查看管道 YAML ”页上,查看管道以查看其用途。 请确保所有默认输入都适用于你的代码。 若要了解管道 YAML 文件架构,请参阅 YAML 架构参考

下面的完整示例 YAML 管道文件将 CI/CD 管道定义为一系列 阶段作业步骤,其中每个步骤都包含不同 任务脚本的详细信息。 生成的 YAML 代码会自动使用应用和连接的值填充占位符。

trigger:
- main

variables:
  # Azure Resource Manager connection created during pipeline creation
  azureServiceConnectionId: '<GUID>'

  # Web app name
  webAppName: '<your-webapp-name>'

  # Agent VM image name
  vmImageName: 'ubuntu-latest'

  # Environment name
  environmentName: '<your-webapp-name>'

  # Project root folder. Point to the folder containing manage.py file.
  projectRoot: $(System.DefaultWorkingDirectory)

  pythonVersion: '3.11'

stages:
- stage: Build
  displayName: Build stage
  jobs:
  - job: BuildJob
    pool:
      vmImage: $(vmImageName)
    steps:
    - task: UsePythonVersion@0
      inputs:
        versionSpec: '$(pythonVersion)'
      displayName: 'Use Python $(pythonVersion)'

    - script: |
        python -m venv antenv
        source antenv/bin/activate
        python -m pip install --upgrade pip
        pip install setuptools
        pip install -r requirements.txt
      workingDirectory: $(projectRoot)
      displayName: "Install requirements"

    - task: ArchiveFiles@2
      displayName: 'Archive files'
      inputs:
        rootFolderOrFile: '$(projectRoot)'
        includeRootFolder: false
        archiveType: zip
        archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
        replaceExistingArchive: true

    - upload: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
      displayName: 'Upload package'
      artifact: drop

- stage: Deploy
  displayName: 'Deploy Web App'
  dependsOn: Build
  condition: succeeded()
  jobs:
  - deployment: DeploymentJob
    pool:
      vmImage: $(vmImageName)
    environment: $(environmentName)
    strategy:
      runOnce:
        deploy:
          steps:

          - task: UsePythonVersion@0
            inputs:
              versionSpec: '$(pythonVersion)'
            displayName: 'Use Python version'

          - task: AzureWebApp@1
            displayName: 'Deploy Azure Web App : $(webAppName)'
            inputs:
              azureSubscription: $(azureServiceConnectionId)
              appName: $(webAppName)
              package: $(Pipeline.Workspace)/drop/$(Build.BuildId).zip
trigger:
- main

variables:
  # Azure Resource Manager connection created during pipeline creation
  azureServiceConnectionId: '<your-service-connection-name>'

  # Web app name
  webAppName: '<your-web-app-name>'

  # Environment name
  environmentName: '<your-web-app-name>'

  # Project root folder. 
  projectRoot: $(System.DefaultWorkingDirectory)

  # Python version: 
  pythonVersion: '<your-python-version>'

stages:
- stage: Build
  displayName: Build stage
  jobs:
  - job: BuildJob
pool:
      name: '<your-pool-name>'
      demands: python
    steps:
    - task: UsePythonVersion@0
      inputs:
        versionSpec: '$(pythonVersion)'
      displayName: 'Use Python $(pythonVersion)'

    - script: |
        python -m venv antenv
        source antenv/bin/activate
        python -m pip install --upgrade pip
        pip install -r requirements.txt
      workingDirectory: $(projectRoot)
      displayName: "Install requirements"

    - task: ArchiveFiles@2
      displayName: 'Archive files'
      inputs:
        rootFolderOrFile: '$(projectRoot)'
        includeRootFolder: false
        archiveType: zip
        archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
        replaceExistingArchive: true

    - task: PublishBuildArtifacts@1
      inputs:
        PathtoPublish: '$(Build.ArtifactStagingDirectory)'
        ArtifactName: 'drop'
        publishLocation: 'Container'

- stage: Deploy
  displayName: 'Deploy Web App'
  dependsOn: Build
  condition: succeeded()
  jobs:
  - deployment: DeploymentJob
    pool:
      name: '<your-pool-name'
    environment: $(environmentName)
    strategy:
      runOnce:
        deploy:
          steps:

          - task: UsePythonVersion@0
            inputs:
              versionSpec: '$(pythonVersion)'
            displayName: 'Use Python version'

          - task: AzureWebApp@1
            displayName: 'Deploy Azure Web App : <your-web-app-name>'
            inputs:
              azureSubscription: $(azureServiceConnectionId)
              appName: $(webAppName)
              package: $(Pipeline.Workspace)/drop/$(Build.BuildId).zip
              startUpCommand: 'startup.txt'

变量

variables YAML 文件开头的部分定义了以下变量:

变量 描述
azureServiceConnectionId Azure 资源管理器服务连接的 ID。
webAppName 应用服务 Web 应用的名称。
vmImageName 要用于生成代理的操作系统的名称。
environmentName 要部署到的环境的名称,部署作业运行时会自动创建该环境。
projectRoot 包含应用代码的根文件夹。
pythonVersion 要在生成与部署代理上使用的 Python 版本。
变量 描述
azureServiceConnectionId Azure 资源管理器服务连接的 ID。
webAppName 应用服务 Web 应用的名称。
environmentName 要部署到的环境的名称,部署作业运行时会自动创建该环境。
projectRoot 包含应用代码的文件夹。 该值为自动系统变量。
pythonVersion 要在生成与部署代理上使用的 Python 版本。

生成和部署阶段

管道由生成和部署阶段组成。

生成阶段

生成阶段包含一个作业,该作业在变量中vmImageName定义的作系统上运行,在本例中。ubuntu-latest

  - job: BuildJob
    pool:
      vmImage: $(vmImageName)

生成阶段包含一个作业,该作业在由参数标识poolname代理上运行。

可使用 demands 关键字指定代理功能。 例如,demands: python 指定代理必须已安装 Python。 若要按名称指定自承载代理,可以使用 demands: Agent.Name -equals <agent-name>

  - job: BuildJob
    pool:
      name: <your-pool-name>
      demands: python

此作业包含多个步骤:

  1. 首先, UsePythonVersion 任务选择要使用的 Python 版本,如变量中 pythonVersion 定义。

       - task: UsePythonVersion@0
          inputs:
            versionSpec: '$(pythonVersion)'
            displayName: 'Use Python $(pythonVersion)'
    
  2. 下一步使用创建虚拟 Python 环境的脚本,并从中安装应用的依赖项 requirements.txt。 该 workingDirectory 参数指定应用代码的位置。

       - script: |
            python -m venv antenv
            source antenv/bin/activate
            python -m pip install --upgrade pip
            pip install setuptools
            pip install  -r ./requirements.txt
          workingDirectory: $(projectRoot)
          displayName: "Install requirements"
    
  3. ArchiveFiles 任务创建包含生成的 Web 应用的 ZIP 存档。

        - task: ArchiveFiles@2
          displayName: 'Archive files'
          inputs:
            rootFolderOrFile: '$(projectRoot)'
            includeRootFolder: false
            archiveType: zip
            archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
            replaceExistingArchive: true
    

    参数按如下方式设置:

    参数 描述
    rootFolderOrFile 应用代码的位置。
    includeRootFolder 是否在 .zip 文件中包括根文件夹。 设置为 false。 如果设置为 true 则.zip 文件的内容将放入名为 s 的文件夹中,任务找不到应用代码。
    archiveType 要创建的存档的类型。 设置为 zip
    archiveFile 要创建的 .zip 文件的所在位置。
    replaceExistingArchive 表示当此文件已存在时是否替换现有存档。 设置为 true
  4. 然后,该文件作为名为 <a0/> 的项目上传到管道。 部署阶段使用 .zip 文件来部署应用。

        - upload: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
          displayName: 'Upload package'
          artifact: drop
    
    • upload 参数设置 要上传的.zip 文件的位置和名称。
    • artifact 参数将创建的项目的名称设置为 drop

部署阶段

如果生成阶段成功完成,则部署阶段将运行。 和dependsOncondition关键字定义此行为。

  dependsOn: Build
  condition: succeeded()

部署阶段包含配置如下的单个部署作业。

  - deployment: DeploymentJob
    pool:
      vmImage: $(vmImageName)
    environment: $(environmentName)
  • 关键字deployment指示作业是面向要部署到的环境部署作业environment运行作业时,会自动在项目中创建该作业。

  • 此参数 pool 指定部署代理池,如果未 name 指定默认代理池,则使用默认代理池。 代理在变量中vmImageName定义的作系统上运行,在本例中。ubuntu-latest

  - deployment: DeploymentJob
    pool:
      name: <your-pool-name>
    environment: $(environmentName)
  • 关键字deployment指示作业是面向要部署到的环境部署作业environment运行作业时,会自动在项目中创建该作业。

  • pool 参数指定部署代理池,并且必须包含一个代理,该代理能够运行管道中指定的 Python 版本。

关键字 strategy 定义部署策略。

  strategy:
    runOnce:
      deploy:
        steps:
  • runOnce 关键字可指定该部署作业仅运行一次。
  • 关键字 deploy 指定要 steps 在部署作业中运行的。

steps此阶段运行以下任务:

  1. UsePythonVersion@0 选择要使用的 Python 版本,与 在生成阶段相同。
  2. AzureWebApp@1 部署 Web 应用和 drop ZIP 项目。
- task: AzureWebApp@1
    displayName: 'Deploy Azure Web App : <your-web-app-name>'
  inputs:
    azureSubscription: $(azureServiceConnectionId)
    appName: $(webAppName)
    package: $(Pipeline.Workspace)/drop/$(Build.BuildId).zip
  • azureSubscription 参数包含 azureServiceConnectionId 管道变量中指定的值。
  • 包含 appName 变量的值 webAppName
  • 指定要 package 部署 的.zip 文件的名称和位置。

此外,由于 python-vscode-flask-tutorial 存储库在名为 startup.txt的文件中包含应用启动命令,因此可以通过添加参数来指定应用启动命令: startUpCommand: 'startup.txt'

运行管道

现在可以试用管道了。

  1. 在管道编辑器中,选择“ 保存并运行”。

  2. “保存并运行 ”屏幕上,根据需要添加提交消息,然后选择“ 保存并运行”。

    可以通过在管道摘要页上选择“阶段”或“作业”来监视管道运行。 每个作业和阶段都会在成功完成时显示绿色复选标记。 如果发生错误,它们会显示在摘要或作业步骤中。

    “管道运行摘要阶段”部分的屏幕截图。

    可以通过选择“ 摘要 ”页上右上角的垂直点并选择 “编辑管道”来快速返回到 YAML 编辑器。

    生成报表中编辑管道注释的屏幕截图。

  3. 在部署作业中,选择部署 Azure Web 应用任务可显示其输出。

    管道阶段步骤的屏幕截图。

  4. 在输出中,选择 应用服务应用程序 URL 之后的 URL。 应用应如下所示:

    一个屏幕截图,其中显示了应用服务上运行的示例应用的视图。

注意

如果应用部署由于缺少依赖项而失败, 则部署 期间未处理requirements.txt文件。 如果在门户中直接创建 Web 应用,而不是使用 az webapp up 命令,则可能会出现此问题。

az webapp up 命令专门将生成操作 SCM_DO_BUILD_DURING_DEPLOYMENT 设置为 true。 如果通过门户预配应用服务,则不会自动设置此作。

若要设置此作,请执行以下作:

  1. 在 Web 应用的门户页上,从左侧导航菜单中选择 “配置 ”。
  2. 在“ 应用程序设置” 选项卡上,选择“ 新建应用程序设置”。
  3. 在显示的弹出窗口中,将名称设置为 SCM_DO_BUILD_DURING_DEPLOYMENT,将设置为 true,然后选择确定
  4. 选择保存配置页的顶部。
  5. 再次运行管道。 依赖项现在应在部署期间安装。

触发管道运行

每当更改签入代码存储库时,此管道都会设置为运行。 若要触发管道运行,请将某一更改提交到此存储库。 例如,可向该应用添加新功能,或更新该应用的依赖项。

  1. 转到应用的 GitHub 存储库。
  2. 更改代码,例如更改此应用的标题。
  3. 提交更改。
  4. 转到管道,验证是否已创建新运行并正在运行。
  5. 运行完成后,请验证是否已将更改部署到 Web 应用。
  6. 在 Azure 门户中,转到 Web 应用,然后从左侧导航菜单中选择 部署中心
  7. 选择“ 日志 ”选项卡并验证是否已列出新部署。

将 Django 应用部署到应用服务

如果使用单独的数据库,可以使用 Azure Pipelines 将 Django 应用部署到 Linux 上的应用服务。 不能使用 SQLite 数据库,因为应用服务会锁定 db.sqlite3 文件,从而阻止读取和写入。 此行为不会影响外部数据库。

容器启动过程中所述,应用服务会在应用代码中自动查找 wsgi.py 文件,该文件通常包含应用对象。 若要自定义启动命令,请使用 startUpCommand YAML 管道文件中的步骤中的 AzureWebApp@1 参数。

使用 Django 时,通常需要在部署应用代码后使用 manage.py migrate 迁移数据模型。 为此,可使用部署后脚本添加 startUpCommand。 例如,下面是 AzureWebApp@1 任务中的 startUpCommand 属性。

  - task: AzureWebApp@1
      displayName: 'Deploy Azure Web App : $(webAppName)'
      inputs:
        azureSubscription: $(azureServiceConnectionId)
        appName: $(webAppName)
        package: $(Pipeline.Workspace)/drop/$(Build.BuildId).zip
        startUpCommand: 'python manage.py migrate'

在生成代理上运行测试

生成过程中,你可能想对应用代码运行测试。 由于测试会在生成代理上运行,因此需将依赖项安装到生成代理的虚拟环境中。 测试运行后,请先删除测试虚拟环境,然后再创建用于部署 的.zip 文件。

以下脚本元素演示了此过程。 将它们放在 ArchiveFiles@2 任务之前的 azure-pipelines.yml 文件中。 有关详细信息,请参阅运行跨平台脚本

# The | symbol is a continuation character, indicating a multi-line script.
# A single-line script can immediately follow "- script:".
- script: |
    python -m venv .env
    source .env/bin/activate
    pip install setuptools
    pip install -r requirements.txt

  # The displayName shows in the pipeline UI when a build runs
  displayName: 'Install dependencies on build agent'

- script: |
    # Put commands to run tests here
    displayName: 'Run tests'

- script: |
    echo Deleting .env
    deactivate
    rm -rf .env
  displayName: 'Remove .env before zip'

此外,还可使用 PublishTestResults@2 等任务将测试结果发布到管道。 有关详细信息,请参阅 “运行测试”。

清理资源

如果已完成本教程中创建的 Azure 资源,请将其删除,以避免产生进一步的费用。

  • 删除创建的 Azure DevOps 项目。 删除此项目会同时删除管道和服务连接。
  • 删除包含应用服务和应用服务计划的 Azure 资源组。 在 Azure 门户中,转到资源组,选择删除资源组,然后按提示进行操作。
  • 删除维护 Cloud Shell 文件系统的 Azure 存储帐户。 关闭 Cloud Shell,然后找到以 cloud-shell-storage 开头的资源组。 选择 “删除资源组”,然后按照提示进行作。