你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

使用 Azure Pipelines 部署到应用服务

Azure DevOps Services | Azure DevOps Server 2020 | Azure DevOps Server 2019

每次成功生成后,使用 Azure Pipelines 自动将 Web 应用部署到 Azure 应用服务。 利用 Azure Pipelines,可以使用 Azure DevOps 通过持续集成 (CI) 和持续交付 (CD) 来进行生成、测试和部署。

YAML 管道是使用存储库中的 YAML 文件定义的。 步骤是管道的最小组成要素,并且可以是脚本或任务(预打包的脚本)。 了解构成管道的关键概念和组件

你将在管道中使用 Azure Web 应用任务 (AzureWebApp) 部署到 Azure 应用服务。 对于更复杂的方案(例如需要在部署中使用 XML 参数),可以使用 Azure 应用服务部署任务 (AzureRmWebAppDeployment)

先决条件

1.为堆栈创建管道

本部分的代码示例假设你正在部署一个 ASP.NET Web 应用。 可以调整适用于其他框架的说明。

详细了解 Azure Pipelines 生态系统支持

  1. 登录到 Azure DevOps 组织,并导航到你的项目。

  2. 转到“管道”,然后选择“新建管道”。

  3. 出现提示时,请选择源代码的位置:Azure Repos Git 或 GitHub。

    可能会重定向到 GitHub 进行登录。 如果是这样,请输入 GitHub 凭据。

  4. 显示存储库列表时,选择你的存储库。

  5. 你可能会被重定向到 GitHub 来安装 Azure Pipelines 应用。 如果是,请选择批准并安装

  6. 出现“配置”选项卡时,选择“ASP.NET Core”。

  7. 当新管道出现时,请查看 YAML 以了解其功能。 准备就绪后,选择“保存并运行”。

2.添加部署任务

  1. 单击 YAML 文件的末尾,然后选择“显示助手”

  2. 使用任务助手添加 Azure Web 应用任务。

    Screenshot of Azure web app task.

    或者,可以添加 Azure 应用服务部署 (AzureRmWebAppDeployment) 任务。

  3. 选择你的 Azure 订阅。 确保为连接授权。 该授权可创建所需的服务连接。

  4. 根据应用服务应用选择应用类型、应用名称和运行时堆栈。 完整的 YAML 应如以下代码所示。

    variables:
      buildConfiguration: 'Release'
    
    steps:
    - script: dotnet build --configuration $(buildConfiguration)
      displayName: 'dotnet build $(buildConfiguration)'
    - task: DotNetCoreCLI@2
      inputs:
        command: 'publish'
        publishWebProjects: true
    - task: AzureWebApp@1
      inputs:
        azureSubscription: '<service-connection-name>'
        appType: 'webAppLinux'
        appName: '<app-name>'
        package: '$(System.DefaultWorkingDirectory)/**/*.zip'
    
    • azureSubscription:与 Azure 订阅的授权服务连接的名称
    • appName:现有应用的名称
    • package:包含应用服务内容的包或文件夹的文件路径。 支持通配符。

示例:部署 .NET 应用

若要将 .zip Web 包(例如,从 ASP.NET Web 应用)部署到 Azure Web 应用,请使用以下代码片段将生成部署到应用。

variables:
  buildConfiguration: 'Release'

steps:
- script: dotnet build --configuration $(buildConfiguration)
  displayName: 'dotnet build $(buildConfiguration)'
- task: DotNetCoreCLI@2
  inputs:
    command: 'publish'
    publishWebProjects: true
- task: AzureWebApp@1
  inputs:
    azureSubscription: '<service-connection-name>'
    appType: 'webAppLinux'
    appName: '<app-name>'
    package: '$(System.DefaultWorkingDirectory)/**/*.zip'
  • azureSubscription:你的 Azure 订阅。
  • appType:你的 Web 应用类型。
  • appName:现有应用服务的名称。
  • package:包的文件路径或包含应用服务内容的文件夹。 支持通配符。

示例:部署到虚拟应用程序

默认情况下,部署发生在 Azure Web 应用中的根应用程序。 可以使用 Azure 应用服务 (AzureRmWebAppDeployment) 任务的 VirtualApplication 属性部署到特定虚拟应用程序:

- task: AzureRmWebAppDeployment@4
  inputs:
    VirtualApplication: '<name of virtual application>'

示例:部署到槽

以下示例演示如何部署到过渡槽,然后交换到生产槽:

- task: AzureWebApp@1
  inputs:
    azureSubscription: '<service-connection-name>'
    appType: webAppLinux
    appName: '<app-name>'
    deployToSlotOrASE: true
    resourceGroupName: '<name of resource group>'
    slotName: staging
    package: '$(Build.ArtifactStagingDirectory)/**/*.zip'

- task: AzureAppServiceManage@0
  inputs:
    azureSubscription: '<service-connection-name>'
    appType: webAppLinux
    WebAppName: '<app-name>'
    ResourceGroupName: '<name of resource group>'
    SourceSlot: staging
    SwapWithProduction: true
  • azureSubscription:你的 Azure 订阅。
  • appType:(可选)使用 webAppLinux 部署到 Linux 上的 Web 应用。
  • appName:现有应用服务的名称。
  • deployToSlotOrASE:布尔值。 部署到现有部署槽或 Azure 应用服务环境。
  • resourceGroupName:资源组的名称。 如果 deployToSlotOrASE 为 true,则是必需的。
  • slotName:槽的名称,默认为 production。 如果 deployToSlotOrASE 为 true,则是必需的。
  • package:包的文件路径或包含应用服务内容的文件夹。 支持通配符。
  • SourceSlot:当 SwapWithProduction 为 true 时发送到生产环境的槽。
  • SwapWithProduction:布尔值。 交换源槽与生产槽的流量。

示例:部署到多个 Web 应用

可以使用 YAML 文件中的作业来设置部署管道。 使用作业可以控制部署到多个 Web 应用时所遵循的顺序。

jobs:
- job: buildandtest
  pool:
    vmImage: ubuntu-latest
 
  steps:
  # publish an artifact called drop
  - task: PublishPipelineArtifact@1
    inputs:
      targetPath: '$(Build.ArtifactStagingDirectory)' 
      artifactName: drop
  
  # deploy to Azure Web App staging
  - task: AzureWebApp@1
    inputs:
      azureSubscription: '<service-connection-name>'
      appType: <app type>
      appName: '<staging-app-name>'
      deployToSlotOrASE: true
      resourceGroupName: <group-name>
      slotName: 'staging'
      package: '$(Build.ArtifactStagingDirectory)/**/*.zip'

- job: deploy
  dependsOn: buildandtest
  condition: succeeded()

  pool: 
    vmImage: ubuntu-latest  
  
  steps:
    # download the artifact drop from the previous job
  - task: DownloadPipelineArtifact@2
    inputs:
      source: 'current'
      artifact: 'drop'
      path: '$(Pipeline.Workspace)'

  - task: AzureWebApp@1
    inputs:
      azureSubscription: '<service-connection-name>'
      appType: <app type>
      appName: '<production-app-name>'
      resourceGroupName: <group-name>
      package: '$(Pipeline.Workspace)/**/*.zip'

示例:进行变量替换

对于大多数语言堆栈,可以在运行时将应用设置连接字符串设置为环境变量。

但还有其他原因需要对 Web.config 进行变量替换。在此示例中,Web.config 文件包含名为 connectionString 的连接字符串。 在部署到每个 Web 应用之前,可以更改其值。 为此,可以应用 Web.config 转换或者替换 Web.config 文件中的变量。

以下代码片段使用 Azure 应用服务部署 (AzureRmWebAppDeployment) 任务演示了变量替换的示例:

jobs:
- job: test
  variables:
    connectionString: <test-stage connection string>
  steps:
  - task: AzureRmWebAppDeployment@4
    inputs:
      azureSubscription: '<Test stage Azure service connection>'
      WebAppName: '<name of test stage web app>'
      enableXmlVariableSubstitution: true

- job: prod
  dependsOn: test
  variables:
    connectionString: <prod-stage connection string>
  steps:
  - task: AzureRmWebAppDeployment@4
    inputs:
      azureSubscription: '<Prod stage Azure service connection>'
      WebAppName: '<name of prod stage web app>'
      enableXmlVariableSubstitution: true

示例:有条件部署

若要在 YAML 中执行此操作,可使用以下方法之一:

  • 将部署步骤隔离到单独的作业中,并向该作业添加条件。
  • 向步骤添加条件。

以下示例演示如何使用步骤条件来仅部署源自主分支的生成:

- task: AzureWebApp@1
  condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
  inputs:
    azureSubscription: '<service-connection-name>'
    appName: '<app-name>'

若要详细了解条件,请参阅指定条件

示例:使用 Web 部署进行部署

Azure 应用服务部署 (AzureRmWebAppDeployment) 任务可以使用 Web 部署部署到应用服务。

trigger:
- main

pool:
  vmImage: windows-latest

variables:
  buildConfiguration: 'Release'

steps:
- script: dotnet build --configuration $(buildConfiguration)
  displayName: 'dotnet build $(buildConfiguration)'
- task: DotNetCoreCLI@2
  inputs:
    command: 'publish'
    publishWebProjects: true
    arguments: '--configuration $(buildConfiguration)'
    zipAfterPublish: true
- task: AzureRmWebAppDeployment@4
  inputs:
    ConnectionType: 'AzureRM'
    azureSubscription: '<service-connection-name>'
    appType: 'webApp'
    WebAppName: '<app-name>'
    packageForLinux: '$(System.DefaultWorkingDirectory)/**/*.zip'
    enableCustomDeployment: true
    DeploymentType: 'webDeploy'

常见问题

AzureWebAppAzureRmWebAppDeployment 任务之间有何差异?

Azure Web 应用任务 (AzureWebApp) 是部署到 Azure Web 应用的最简单方法。 默认情况下,部署发生在 Azure Web 应用中的根应用程序。

Azure 应用服务部署任务 (AzureRmWebAppDeployment) 可以处理更多自定义方案,例如:

注意

用于 Azure Pipelines 的单独文件转换任务也支持文件转换和变量替换。 可以使用文件转换任务对任何配置文件及参数文件应用文件转换和变量替换。

我收到消息“提供的应用服务包或文件夹路径无效。”

在 YAML 管道中,根据管道的不同,生成的 Web 包的保存位置和部署任务的查找位置之间可能不匹配。 例如,AzureWebApp 任务为部署选取 Web 包。 例如,AzureWebApp 任务在 $(System.DefaultWorkingDirectory)/**/*.zip 中进行查找。 如果 Web 包存放在其他位置,请修改 package 的值。

我收到消息“仅当使用 Windows 代理时才支持使用 webdeploy 选项进行发布。”

将任务配置为使用 Web 部署进行部署,但代理未运行 Windows 时,AzureRmWebAppDeployment 任务中会出现此错误。 验证你的 YAML 具有如下所示的代码:

pool:
  vmImage: windows-latest

禁用基本身份验证时,Web 部署不起作用

有关配合使用 Microsoft Entra ID 身份验证与 AzureRmWebAppDeployment 任务的故障排除信息,请参阅无法从 Windows 代理使用 Microsoft Entra ID 身份验证将 Web 部署到 Azure 应用服务

后续步骤