将 Azure DevOps 中的选定工件作为 Docker 映像部署到 ECR

环境

  • Azure Dev Ops(代码仓库和管道触发器)
  • AWS ECR/ECS(目标部署平台)
  • 码头工人
  • .NET Core Web 应用程序 (v5.0)

现在的情况

目前使用 dotnet build(powershell 脚本)构建应用程序,并使用 azurepipeline.yml 将 zip 文件推送到 Azure DevOps 工件。这很好。我为 ECR Push 添加了另一个任务,它还使用源代码中的 Dockerfile 将生成的 docker 映像推送到 ECR。

业务问题

我们希望能够在 Azure Artifact 中选择特定的构建(例如 0.1.24)(使用变量提供版本号),并使用相应的二进制文件和 Dockerfile 生成 Docker 构建。我无法找到这样做的方法。具体任务如下:-

  1. 使用工件 id 或名称部署用户更新变量“versionNoToDeploy”
    2.部署用户运行特定管道
  2. 管道找到工件(假设它有效,否则发送错误),在临时位置解压缩包( -need help on
  3. 管道运行 dockerfile 来构建镜像(-known & working)
  4. Pipeline 将此图像推送到 ECR (-known & working)

目的是继续构建分支,直到我们获得稳定的构建。此版本手动部署在测试服务器上并经过测试。构建获得认证后,需要将其推送到生产 ECR/ECS 实例。

我们的管道(仅限特定代码)

- pwsh: ./build.ps1 --target Clean Protolint Compile --runtime $(runtime) 
  displayName: ⚙️ Compile

- task: Docker@2
  displayName: Build
  inputs:
     command: build
     repository: appRepo
     tags: |
       $(Build.BuildId)
       deploy
     addPipelineData: true
     Dockerfile: srcDockerfileNew

- task: ECRPushImage@1
  inputs:
     awsCredentials: 'AWS ECR Connection'
     regionName: 'ap-south-1'
     imageSource: 'imagename'
     sourceImageName: 'myApplication'
     sourceImageTag: 'deploy'
     repositoryName: 'devops-demo'
     outputVariable: 'imageTagOutputVar'

- pwsh: ./build.ps1 --target Test Coverage --skip
  displayName: 🚦 Test

- pwsh: ./build.ps1 --target BuildImage Pack --runtime $(runtime) --skip
  displayName: 📦 Pack

- pwsh: ./build.ps1 --target Publish --runtime $(runtime) --skip
  displayName: 🚚 Publish

工件详细信息

enter image description here

可以提供所需的任何特定方面

stack overflow Deploy selected artifact in Azure DevOps as docker image to ECR
原文答案
author avatar

接受的答案

最后,在大量使用管道并自定义调整各个步骤之后,我得出了以下结果(摘自 yml)。

这涉及将构建版本存储在变量中,该变量在管道的每个步骤中都被引用。管理员必须决定他们是否想要一个通用的构建,生成一个工件;或者只是将特定构建部署到 AWS。具有 build-id 的变量是有条件地评估的,并基于此,执行或绕过这些步骤。

- pwsh: ./build.ps1 --target Clean Protolint Compile --runtime $(runtime)
  condition: eq(variables['artifactVersionToPush'], '')
  displayName: ⚙️ Compile

- task: DownloadBuildArtifacts@0
  condition: ne(variables['artifactVersionToPush'], '')
  inputs:
     buildType: 'specific'
     project: 'NitinProj'
     pipeline: 'NitinProj'
     buildVersionToDownload: specific
     buildId: $(artifactVersionToPush)
     downloadType: 'single'
     artifactName: 'app'
     downloadPath: '$(System.ArtifactsDirectory)'   #(this needs to be mentioned as default is Build directory)

 - task: ExtractFiles@1
   displayName: Extract Artifact to temp location
   condition: ne(variables['artifactVersionToPush'], '')
   inputs:
     archiveFilePatterns: '$(System.ArtifactsDirectory)/app/*.zip'    #path need update
     cleanDestinationFolder: false
     overwriteExistingFiles: true
     destinationFolder: src

 - task: Docker@2
   displayName: Docker Build image with compiled code in artifact
   condition: ne(variables['artifactVersionToPush'], '')
   inputs:
     command: build
     repository: myApp
     tags: |
       $(Build.BuildId)
       deploy
     addPipelineData: true
     Dockerfile: srcDockerfileNew

 - task: ECRPushImage@1
   displayName: Push built image to AWS ECR
   condition: ne(variables['artifactVersionToPush'], '')
   inputs:
     awsCredentials: 'AWS ECR Connection'
     regionName: 'ap-south-1'
     imageSource: 'imagename'
     sourceImageName: 'myApp'
     sourceImageTag: 'deploy'
     pushTag: '$(Build.BuildId)'
     repositoryName: 'devops-demo'
     outputVariable: 'imageTagOutputVar'

 - pwsh: ./build.ps1 --target Test Coverage --skip
   condition: eq(variables['artifactVersionToPush'], '')
   displayName: 🚦 Test

 - pwsh: ./build.ps1 --target BuildImage Pack --runtime $(runtime) --skip
   condition: eq(variables['artifactVersionToPush'], '')
   displayName: 📦 Pack

 - pwsh: ./build.ps1 --target Publish --runtime $(runtime) --skip
   condition: eq(variables['artifactVersionToPush'], '')
   displayName: 🚚 Publish

我将更新此 yml 以将步骤组织到作业中,但这是一个优化故事.. :)


答案:

作者头像

由于此处涉及人工干预,您可以考虑将工作流拆分为多个作业,如下所示:

jobs:
- job: BuildAndDeployToTest
  steps:
  - bash: echo "A"

- job: waitForValidation
    displayName: Wait for external validation
    pool: server
    timeoutInMinutes: 4320 # job times out in 3 days
    steps:
    - task: ManualValidation@0
      timeoutInMinutes: 1440 # task times out in 1 day
      inputs:
        notifyUsers: |
          test@test.com
          example@example.com
        instructions: 'Please validate the build configuration and resume'
        onTimeout: 'resume'  

- job: DeployToProd
  steps:
  - bash: echo "B"

就涉及变量而言,这并不是您想要的,但您将能够实现您的目标。等待验证并部署以仅生产经过验证的构建。

它依赖于 ManualValidation task

另一种方法可能是使用部署作业和批准:

jobs:
- job: BuildAndDeployToTest
  steps:
  - bash: echo "A"

jobs:
  # Track deployments on the environment.
- deployment: DeployToProd
  displayName: deploy Web App
  pool:
    vmImage: 'Ubuntu-16.04'
  # Creates an environment if it doesn't exist.
  environment: 'PROD'
  strategy:
    # Default deployment strategy, more coming...
    runOnce:
      deploy:
        steps:
        - checkout: self 
        - script: echo my first deployment

为此,您需要定义 evnironment 并定义 approval

通过这两种方式,您都可以清楚地了解交付给产品的内容以及批准 PROD 部署的信息。

相关问题