You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Azure中为NextJS应用的每个PR创建预览部署实例

Azure DevOps PR预览Pipeline配置(NextJS + Docker)

我们已在Azure上通过Docker部署NextJS应用,现有三个分支:

  • Dev(开发分支)
  • Staging(预生产分支)
  • Main(生产分支)

开发新功能时会创建feature分支并推送变更,希望在合并至Dev分支前,让利益相关者能查看功能的实时预览(类似Vercel与GitHub的预览功能),同时需要在PR合并后自动删除对应的预览部署实例。

已有的Dev分支合并Pipeline参考:

trigger:
  - dev

variables:
  dockerRegistryServiceConnection: "xxx"
  imageRepository: "xxx"
  containerRegistry: "xxx"
  dockerfilePath: "$(Build.SourcesDirectory)/Dockerfile.prod"
  tag: "$(Build.BuildId)"
  vmImageName: "ubuntu-latest"

pool:
  vmImage: ubuntu-latest

stages:
  - stage: Install
    displayName: "Install"
    jobs:
      - job: InstallJob
        displayName: "Install Node.js and Dependencies"
        steps:
          - task: NodeTool@0
            inputs:
              versionSpec: "20.x"
            displayName: "Install Node.js"
          - script: |
              npm install
            displayName: "Install Node.js and Dependencies"

  - stage: UnitComponentTests
    displayName: "Run Unit and Component Tests"
    jobs:
      - job: UnitComponnentTestsJob
        displayName: "Run Unit  and Component Tests"
        steps:
          - script: |
              npm install
              npm run test
            displayName: "Run Unit and Component Tests"

  - stage: E2ETests
    displayName: "Run E2E Tests"
    jobs:
      - job: E2ETestsJob
        displayName: "Run E2E Tests"
        steps:
          - script: |
              npm install
              npx playwright install
              npm run test-e2e
            displayName: "Run E2E Tests"

  - stage: Build
    displayName: Build
    jobs:
      - job: Build
        displayName: Build
        pool:
          vmImage: $(vmImageName)
        steps:
          - task: Docker@2
            displayName: Build and push an image to container registry
            inputs:
              command: buildAndPush
              repository: $(imageRepository)
              dockerfile: $(dockerfilePath)
              buildContext: "./"
              containerRegistry: $(dockerRegistryServiceConnection)
              tags: |
                $(tag)
                latest

完整PR预览Pipeline配置

# 仅针对目标为dev分支的PR触发,合并后自动执行清理
trigger: none
pr:
  branches:
    include:
      - dev
  paths:
    exclude:
      - README.md # 按需排除无需触发的文件

variables:
  # 通用配置(替换为你的实际值)
  dockerRegistryServiceConnection: "xxx"
  imageRepository: "xxx"
  containerRegistry: "xxx"
  dockerfilePath: "$(Build.SourcesDirectory)/Dockerfile.prod"
  vmImageName: "ubuntu-latest"
  # PR专属标识:用PR编号确保资源唯一
  prNumber: $(System.PullRequest.PullRequestNumber)
  previewImageTag: "pr-$(prNumber)"
  # Azure App Service预览资源配置(替换为你的资源组和服务名称规则)
  appServiceName: "nextjs-preview-pr-$(prNumber)"
  resourceGroupName: "your-resource-group-name"
  azureServiceConnection: "your-azure-service-connection"

pool:
  vmImage: $(vmImageName)

stages:
  # 1. 统一安装依赖并执行所有测试
  - stage: Test
    displayName: "执行测试用例"
    jobs:
      - job: TestJob
        displayName: "安装依赖并运行测试"
        steps:
          - task: NodeTool@0
            inputs:
              versionSpec: "20.x"
            displayName: "安装Node.js"
          - script: |
              npm install
            displayName: "安装项目依赖"
          - script: |
              npm run test
            displayName: "运行单元与组件测试"
          - script: |
              npx playwright install
              npm run test-e2e
            displayName: "运行E2E测试"

  # 2. 构建PR专属Docker镜像
  - stage: BuildPreviewImage
    displayName: "构建PR预览镜像"
    dependsOn: Test
    condition: succeeded()
    jobs:
      - job: BuildJob
        displayName: "构建并推送预览镜像"
        steps:
          - task: Docker@2
            displayName: "构建并推送镜像至容器注册表"
            inputs:
              command: buildAndPush
              repository: $(imageRepository)
              dockerfile: $(dockerfilePath)
              buildContext: "./"
              containerRegistry: $(dockerRegistryServiceConnection)
              tags: |
                $(previewImageTag)

  # 3. 部署PR预览实例(仅当PR处于打开状态时执行)
  - stage: DeployPreview
    displayName: "部署PR预览实例"
    dependsOn: BuildPreviewImage
    condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest'))
    jobs:
      - job: DeployJob
        displayName: "部署至Azure App Service"
        steps:
          - task: AzureWebAppContainer@1
            displayName: "部署预览App Service"
            inputs:
              azureSubscription: $(azureServiceConnection)
              appName: $(appServiceName)
              containers: $(containerRegistry)/$(imageRepository):$(previewImageTag)
              resourceGroupName: $(resourceGroupName)
          - script: |
              echo "✅ 预览部署完成,访问地址:https://$(appServiceName).azurewebsites.net"
            displayName: "输出预览链接"

  # 4. 清理PR预览资源(仅当PR合并完成后执行)
  - stage: CleanupPreview
    displayName: "清理PR预览实例"
    condition: and(succeeded(), eq(variables['System.PullRequest.Status'], 'completed'))
    jobs:
      - job: CleanupJob
        displayName: "删除预览资源"
        steps:
          # 删除预览App Service实例
          - task: AzureCLI@2
            displayName: "删除预览App Service"
            inputs:
              azureSubscription: $(azureServiceConnection)
              scriptType: bash
              scriptLocation: inlineScript
              inlineScript: |
                az webapp delete --name $(appServiceName) --resource-group $(resourceGroupName) --yes
          # 删除容器注册表中的预览镜像(可选,避免镜像堆积)
          - task: AzureCLI@2
            displayName: "删除预览Docker镜像"
            inputs:
              azureSubscription: $(azureServiceConnection)
              scriptType: bash
              scriptLocation: inlineScript
              inlineScript: |
                az acr repository delete --name $(containerRegistry) --repository $(imageRepository) --tag $(previewImageTag) --yes

关键配置说明

  • 触发逻辑:仅监听目标为dev分支的PR,合并后自动触发清理阶段,避免不必要的资源消耗
  • 资源隔离:用PR编号作为镜像标签和App Service名称的后缀,确保每个PR的预览资源独立,不会互相干扰
  • 阶段控制:通过条件判断实现:
    • PR打开时自动构建、部署预览实例
    • PR合并完成后自动删除对应的预览资源
  • 效率优化:将原Pipeline中重复的npm install步骤合并到一个测试阶段,减少冗余操作
  • 可选扩展:可以添加PR评论任务,自动将预览链接评论到PR中,方便利益相关者直接查看

内容的提问来源于stack exchange,提问作者Ala Eddine Menai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 00:32:07