使用TFS玩转Docker自动化部署

北城以北 提交于 2020-01-10 11:15:32

简介

本文将介绍如何通过微软的Team Foundation Server平台,结合Docker完成程序的持续集成、持续部署。这里小编以.NET Core为例向大家分享整个DevOps流水线的搭建过程以及思路,其他语言平台均适用。

 

 

作者:周文洋

LEANSOFT研发总监,认证 Scrum Master,曾为多家客户提供微软Team Foundation Server实施咨询、二次开发、报表定制等服务,包括:中国农业银行,博时基金,斯伦贝谢,京东商城,国电南自等,现负责公司核心产品的开发工作。

流水线概述

 

  • 开发人员编写代码,并提交代码到TFS配置库(Git \ TFVC), 触发持续集成。

  • 构建代理服务器拉取最新代码到服务器,通过Docker容器完成应用的编译、测试工作,并生成镜像推送到镜像仓库,最后更新 docker-compose.yml镜像版本并回传到TFS Build Artifact, 触发持续部署。

  • 构建代理服务器根据目标环境,替换docker-compose.yml内的环境变量,并复制docker-compose.yml文件到目标环境,运行应用。

 

流水线拓扑图

项目配置


在配置TFS持续集成之前,需要先在项目根目录下添加如下几个文件,每个文件独立分工,各负其责,以便我们完成后面的持续集成,持续部署。大家可以根据自己的实际需求来增减。

接下来分别看下几个文件的职责、说明以及具体实现方式。

程序编译发布(容器内):

文件:docker-compose-ci.build.yml
说明:通过微软官方提供的aspnetcore-build镜像,完成.net core程序的编译以及发布。不需要自己安装编译环境,一旦编译完成,容器销毁。

version: '3'
 
services:
labs-ci-build:
image: devopslabs.azurecr.io/aspnetcore-build:1.0-1.1
volumes:
- .:/src
working_dir: /src
command: /bin/bash -c "dotnet restore ./devopslabs/devopslabs.csproj && 
dotnet publish ./devopslabs/devopslabs.csproj 
-c Release -o ./obj/Docker/publish"

 

代码说明:
• 使用微软官方提供的aspnetcore-build:1.0-1.1 镜像,这里我们的镜像存储在微软的Azure Container Registry,大家也可以使用Harbor搭建企业内部的私有镜像仓库。
• 将当前目录(即程序根目录)映射到容器内的”/src”目录
• 工作目录设置为 “/src”目录执行dotnet restore以及dotnet publish命令,完成应用程序的编译以及发布。

单元测试(容器内):

文件:docker-compose-test.yml
说明:通过微软官方提供的aspnetcore-build镜像,完成.net core程序的单元测试,并生成测试结果。

version: '3'
 
services:
devopslabs-ci-test:
image: devopslabs.azurecr.io/aspnetcore-build:1.0-1.1
volumes:
- .:/src
working_dir: /src/DevopslabsTest
command: /bin/bash -c "dotnet restore ./DevopslabsTest.csproj 
&& dotnet test --logger \"trx;logfilename=TEST.xml\""


代码说明:
• 执行dotnet restore以及dotnet test命令,完成单元测试,并发布测试结果。

镜像制作:

文件:Dockerfile
说明:使用微软官方镜像aspnetcore,运行编译后的ASP.NET Core程序。

FROM devopslabs.azurecr.io/aspnetcore:1.1
ARG source
WORKDIR /app
EXPOSE 80
COPY ${source:-obj/Docker/publish} .
ENTRYPOINT ["dotnet", "devopslabs.dll"]


代码说明:

• 基础镜像为aspnetcore:1.1
• 声明变量source
• 设置RUN、CMD、ENTRYPOINT指令的工作路径为“/app”
• 容器对外暴漏80端口
• 如果环境变量source为空则复制”obj/Docker/publish”目录到容器的”/app”目录容器启动时执行”dotnet devopslabs.dll”命令

部署编排:

文件:docker-compose-template.yml
说明:编排模版文件,通过替换编排文件内的镜像标签版本,以及环境变量完成版本更新以及多环境不同配置的部署。

version: '2'
 
services:
devopslabs:
image: devopslabs.azurecr.io/devopslab:%{Build.BuildId}%environment:
- ASPNETCORE_ENVIRONMENT=#{ASPNETCORE_ENVIRONMENT}# 
restart: always
ports:
- "81:80"
 
devopslabs_db:
image: microsoft/mssql-server-linux
environment:
- ACCEPT_EULA=Y
- SA_PASSWORD=********
- TZ=Asia/Shanghai
restart: always
volumes:
- ~/sqlserverdata:/var/opt/mssql/
ports:
- "1433:1433"


代码说明:

• 包含应用层,以及数据层服务
• 应用层的镜像标签为构建编号变量,在执行持续集成的时候被动态替换环境变量为占位符,需要在执行持续部署的时候,根据目标环境更新实际参数(Test、UAT、Production)

持续集成搭建


基础文件准备完成后,就可以配置TFS的持续集成了。
这里用到了两个插件并提供了插件市场的地址,大家可以自己下载安装:

  1. Docker Integration(微软提供的Docker集成工具)

  2. Replace Token (变量替换工具)

 

创建构建定义,添加构建步骤:



Step1:执行docker-compose-ci.build.yml文件,完成程序的编译,发布。
Step2:执行docker-compose-test.yml文件,完成程序的单元测试工作。
Step3:执行Dockerfile文件,完成镜像的构建。
Step4:推送镜像到私有镜像仓库。
Step5:更新docker-compose-template.yml的镜像版本 。
Step6:发布测试结果到TFS。
Step7:发布docker-compose-template.yml文件。

 

测试结果页面如下:

 

Build Artifact:

 

注意:这里的Build Artifact是带有最新镜像版本的编排文件,但是环境变量并没有替换,因为当前状态只是镜像版本确定了,具体是要部署的目标环境暂时不清楚,所以暂时不做替换。

持续发布配置


说明:持续集成已经完成了镜像的生成以及推送,并生成了最新版本的docker-compose编排文件。接下来的工作就是在目标环境执行最新版本的docker-compose.yml完成应用的部署。

创建发布环境- 测试环境:

 

设置环境变量:
由于不同的部署环境往往需要使用不同的配置文件,这里就通过环境变量来决定需要使用哪个配置文件,添加环境变量ASPNETCORE_ENVIRONMENT,并设置对应值,如下图所示:

注意:这里小编只是Demo环境变量的使用方式,实际应用不建议将配置文件打包到容器。

发布步骤:

Step1:替换环境变量
Step2:复制docker-compose.yml文件到目标环境
Step3:启动新版本容器,具体命令如下:

docker stop labs_devopslabs_1 #停止容器docker rm labs_devopslabs_1 #移除容器docker login devopslabs.azurecr.io -u devopslabs -p $(ACR_PASSWORD) #登录镜像仓库,密码设置为环境变量,避免明文显示docker-compose -p labs -f docker-compose-template.yml up -d #启动容器

这样我们就完成了测试环境自动化发布的配置。

创建发布环境 – 生产环境:

部署步骤与测试环境一致,只需要调整部署目标环境以及修改相关环境变量。

仪表盘配置


可以在仪表盘上配置近期代码迁入,持续集成、持续部署情况、以及失败原因。

在TFS Wiki首页,配置当前项目下所有服务的构建状态以及部署状态。

当前项目下所有服务的持续集成、持续部署状态。

总结:

  • DevOps流水线的搭建大大提高了我们产品的部署频率,测试环境每日可以达到几十次甚至上百次的部署频率。测试人员可以提早的介入测试,发现并反馈问题。

  • 容器化编译,让编译服务器更干净,稳定,有效预防了编译服务器软件之间的冲突。一台服务器可以支持多种语言环境的编译工作,大大降低了服务器成本,开发运维无须手工搭建环境,避免了环境不一致等问题。

  • 容器化部署,消除了环境差异问题,保证了环境的一致性,这一点我们特别有感触。我们服务器期间做过多次迁移,很难想象如果没有使用容器,这些复杂的服务部署能不能把我们累死。

  • TFS强大的仪表盘,可以实时的看到当前项目下各个服务的状态,以及服务的发布频率,团队成员可以快速了解当前各个服务的健康状态,及早的发现并解决问题。

转载自:微信

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!