Azure Devops下构建.NET Core项目CI/CD Pipelines

想必大家在工作开发中都有在使用类似Jenkins这种CI/CD工具进行自动化的构造、测试、部署服务,省去在每次发版时进行重复机械的构造、生成镜像、启动容器等操作,使得开发者从繁杂的集成中解脱出来,更专注于业务的开发实现;
当然,个人项目我也想这样去做,毕竟每次因为一个小bug的修复我就需要去重复发版的流程,让我无比的抗拒🤣;服务器资源充足的当然无需考虑,直接部署Jenkins服务,毕竟时开源项目,想怎么来就怎么来;但是,对于我这种家境贫寒的来说,一个Jenkins无疑是让我的服务器雪上加霜了,更何况使用频率也不是很高,所以我选择使用第三方的服务Azure Devops,而且对于个人开发者来说基本等于免费(每个月有1,800 分钟免费作业时间);

准备

我的整条链路是这样的:GitHub -> Azure Devops -> Docker Hub -> HuaWeiCloud ECS,大家根据实际情况进行调整流程大致相同;
以我的链路为例,需要准备如下:

PS:本文重点讲Azure Devops配置过程,其他的大家可以自行搜索教程;

Azure Devops配置

配置前准备

1、创建Project

如果你是新账户,则需要先创建一个Project,存在则跳过;

2、添加Service Connection

此处配置所需的账号授权信息,以便于在Pipelines中使;
PS:此Project下的Service Connection仅能在此Project范围内使用

- 添加GitHub账户配置

  1. 搜索github,然后创建

  1. 填写连接信息,并授权Pipelines

  1. 授权GitHub账号

  1. 保存

- 添加Docker Hub账户配置

  1. 搜索Docker,然后创建

  1. 填写Docker信息

- 添加ECS SSH配置

  1. 搜索SSH,然后创建

  1. 填写SSH信息

- 完成配置

创建Pipelines并配置

1、创建Pipeline

2、选择代码仓库

3、选择你的Pipeline配置类型,这里我们需要构建Docker Image

4、进行azure-pipelines.yml配置


如上配置为默认生成的配置yml文件,实际这些配置并不符合我们的要求的,我们需要它做到:

  • 拉取GitHub仓库最新代码;
  • 替换appsettingds.Production.json文件(.NET Core配置文件)的敏感信息;
  • 构建项目Docker镜像,并推送到Docker Hub;
  • 在服务环境下删除该项目的容器、镜像,并进行最新镜像的拉取并部署容器;

详细的配置及相关文档信息请移步Azure官方文档:Azure DevOps

最终,修改完后的yml如下:

# Docker
# Build a Docker image
# https://docs.microsoft.com/azure/devops/pipelines/languages/docker

# 管道触发器,具体:https://docs.microsoft.com/zh-cn/azure/devops/pipelines/build/triggers?view=azure-devops
# 此处触发条件为当推送标签为release-*时触发
trigger:
 tags:
   include:
     - release-* # *代表通配符,例如:release-20210321 可以触发

# 表示资源为YML所在的仓储,你也可以指定某个管道的资源
resources:
- repo: self

# 定义变量,使用:$(变量名),例如:$(containerName)
variables:
  tag: '$(Build.BuildId)'
  containerName: azuredevopstest
  imageName: memoyu/azuredevopstest
  appsettings: Azure.Devops.Test/appsettings.Production.json

# 阶段集合定义,我们这比较简单,只需一个阶段即可
stages:
- stage: Build
  displayName: build api
  
  # 做业集合定义,每个作业其内部是顺序运行的步骤集合
  jobs:
  - job: Build
    pool:
      vmImage: ubuntu-latest
    steps:
    
    # 步骤1:执行shell进行配置文件appsettings.Production.json值的替换
    - script: |
        echo ready to execute command
        ls
        # 此处进行替换,使用sed进行配置文件指定值替换
        sed -i 's/{MySqlConStr}/$(MySqlConStr)/g' $(appsettings)
        sed -i 's/{ConfigVal}/$(ConfigVal)/g' $(appsettings)
        # 打印替换后的配置文件内容
        echo "================= print file $(appsettings) start ===================="
        cat $(appsettings) | while read line; do echo $line ; done
        echo "================= print file $(appsettings) end ===================="
        echo command executed
      displayName: 'replace config value'
      
    # 步骤2:构建Docker Image,完成后推送到Docker Hub
    - task: Docker@2
      displayName: 'build docker image and push'
      inputs:
        containerRegistry: 'MemoyuDockerHub'
        repository: $(imageName)
        command: 'buildAndPush'
        Dockerfile: '$(Build.SourcesDirectory)/docker/Dockerfile' # 注意填写正确的Dockerfile地址
        buildContext: $(Build.Repository.LocalPath) # 构建镜像的上下文路径,当前为源代码文件的本地路径(使用了预定义变量)
        tags: 'latest'
        
    # 步骤3:连接服务SSH,进行旧容器、镜像删除,然后拉取新镜像并运行镜像
    - task: SSH@0
      displayName: 'run api container'
      inputs:
        sshEndpoint: 'HuaWeiCloud'
        runOptions: 'inline'
        inline: |
          echo "================= to del container ===================="
          # 判断是否存在容器
          docker ps | grep $(containerName) &> /dev/null
          # 如果不存在,则Remove
          if [ $? -ne 0 ]
          then
              echo "$(containerName) container not exist continue.. "
          else
              echo "remove $(containerName) container"
              docker kill $(containerName)
              docker rm $(containerName)
          fi

          echo "================= to rm image ===================="
          # 判断是否存在镜像
          docker images | grep $(imageName) &> /dev/null
          # 如果不存在,不做操作
          if [ $? -ne 0 ]
          then
              echo "image does not exist , continue..."
          else
              echo "image exists !!! remove it"
              docker rmi $(imageName)
          fi

          echo "================= to pull image ===================="
          docker pull $(imageName)

          echo "================= to run container ===================="
          docker run --name $(containerName) -d -p 5100:80 $(imageName)

          echo "================= publish success ===================="
        readyTimeout: '20000'

1-使用定义的Service Connection

两种方式去使用:

  • 手敲yaml,引入connection(确保参数无)
  • 使用预定义Tasks模板生成

此处例子采用模板生成,且以构建 Docker Build Task 为例:

  • 定位要插入的行

  • 搜索模板

  • 键入关键参数

  • 点击Add,光标对应位置会生成插入yaml

2-定义自定义变量

  • 弹出定义变量侧边栏


  • 新增变量,实际使用如下有表述,且变量的作用范围仅在此Pipeline内

相关链接

测试项目:Azure.Devops.Test

posted @ 2022-03-21 14:07  Memoyu  阅读(289)  评论(0编辑  收藏  举报