限时 發表於 2019-8-8 23:26:00

.Net Core in Docker - 使用阿里云Codepipeline及阿里云容器镜像服务实现持续集成(CI)

<p>前面已经介绍过了 .Net Core 程序发布到 Docker 容器的内容。但是每次通过 SSH 链接到服务器敲命令,运行脚本也是挺麻烦的一件事。程序员是最懒的,能让电脑解决的问题绝不手动解决,如果当我们push一次代码后自动build代码,自动跑单元测试,如果测试通过,自动发布程序,如果失败就发邮件通知管理员,这样的话该多美好。为了达成这个目标于是持续集成(CI)持续交付/部署(CD)就被发明出来了。CICD领域有个大名鼎鼎的工具:Jenkins,但是这次不使用它。如果你使用阿里云的话,阿里云已经提供了类似的功能,可以免去自己搭建Jenkins服务,以及Docker镜像私仓的过程,而且目前它们是免费的。</p>
<h3 id="阿里云codepipeline服务是一套类似jenkins的服务其实我觉得它的核心引擎就是来自jenkins">阿里云Codepipeline服务,是一套类似Jenkins的服务(其实我觉得它的核心引擎就是来自Jenkins)。</h3>
<h3 id="阿里云容器镜像服务是一个镜像仓库可以是公开的也可以是私有的">阿里云容器镜像服务,是一个镜像仓库,可以是公开的,也可以是私有的。</h3>
<h3 id="持续集成ci">持续集成CI</h3>
<p>持续集成指的是,频繁地(一天多次)将代码集成到主干。<br>
它的好处主要有两个。</p>
<pre><code>(1)快速发现错误。每完成一点更新,就集成到主干,可以快速发现错误,定位错误也比较容易。

(2)防止分支大幅偏离主干。如果不是经常集成,主干又在不断更新,会导致以后集成的难度变大,甚至难以集成。
</code></pre>
<p>持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。<br>
Martin Fowler说过,"持续集成并不能消除Bug,而是让它们非常容易发现和改正。"<br>
<em>摘自阮一峰大神的blog</em></p>
<p>下面就演示一下如何通过阿里云Codepipeline跟容器镜像服务来实现 .Net Core 程序的CICD。</p>
<h2 id="持续集成">持续集成</h2>
<h3 id="流程">流程</h3>
<p><img src="https://images.cnblogs.com/cnblogs_com/kklldog/1401672/o_QQ%E6%88%AA%E5%9B%BE20190808230459.png" alt="" loading="lazy"><br>
<em>代码push后Gitee通过webhook功能触发Codepipeline构建,构建成功后自动推送镜像到容器镜像服务</em></p>
<h3 id="新建一个-net-core-mvc-的程序">新建一个 .Net Core MVC 的程序</h3>
<p><img src="https://images.cnblogs.com/cnblogs_com/kklldog/1401672/o_QQ%E6%88%AA%E5%9B%BE20190808000646.png" alt="" loading="lazy"><br>
<em>新建一个 .net core mvc 程序名叫CoreCICDTest</em></p>
<pre><code>    public class Program
    {
      public static void Main(string[] args)
      {
            CreateWebHostBuilder(args).Build().Run();
      }

      public static IWebHostBuilder CreateWebHostBuilder(string[] args) =&gt;
            WebHost.CreateDefaultBuilder(args)
                .UseStartup&lt;Startup&gt;()
               .UseKestrel(options =&gt;
               {
                     options.Listen(IPAddress.Any, 5000);
               });
    }
</code></pre>
<p><em>修改Program的main方法,使Kestrel监听5000端口</em></p>
<pre><code>@{
    ViewData["Title"] = "Home Page";
}


&lt;h3&gt;
    .NET CORE CICD TEST -- V 1.0
&lt;/h3&gt;
</code></pre>
<p><em>修改Home/index视图</em><br>
<img src="https://images.cnblogs.com/cnblogs_com/kklldog/1401672/o_TIM%E6%88%AA%E5%9B%BE20190805105003.jpg" alt="" loading="lazy"><br>
<em>运行一下看看效果,网站正常显示 .NET CORE CICD TEST -- V 1.0</em></p>
<h3 id="新建一个-mstest-项目">新建一个 MSTest 项目</h3>
<p><img src="https://images.cnblogs.com/cnblogs_com/kklldog/1401672/o_QQ%E6%88%AA%E5%9B%BE20190807224944.png" alt="" loading="lazy"><br>
<em>在CoreCICDTest的解决方案下新建一个 MSTest 项目用来写单元测试,名叫CoreCICDTest.Tests</em></p>
<pre><code>   
    public class UnitTest1
    {
      
      public void TestMethod1()
      {
            string str = "00";

            Assert.AreEqual(str, "00");
      }
    }
</code></pre>
<p><em>修改UnitTest1文件中的TestMethod1方法,使其成为一个合法的TestMethod</em><br>
<img src="https://images.cnblogs.com/cnblogs_com/kklldog/1401672/o_QQ%E6%88%AA%E5%9B%BE20190808004542.png" alt="" loading="lazy"><br>
<em>运行一下单元测试,全部通过</em></p>
<h3 id="添加dockerfile文件">添加Dockerfile文件</h3>
<pre><code>FROM microsoft/dotnet:latest AS build
WORKDIR /app
COPY /. /app
RUN dotnet restore
WORKDIR /app/CoreCICDTest.Tests
RUN dotnet test CoreCICDTest.Tests.csproj
WORKDIR /app/CoreCICDTest
RUN dotnet publish -o ./out -c Release
EXPOSE 5000
ENTRYPOINT ["dotnet", "out/CoreCICDTest.dll"]

</code></pre>
<p><em>Dockerfile注意文件名没有任何后缀,Dockerfile用来在Docker容器内自动test、build我们的代码</em></p>
<h3 id="在gitee上新建一个项目并把corecicdtest解决方案推送上去">在Gitee上新建一个项目,并把CoreCICDTest解决方案推送上去</h3>
<p>使用Gitee的免费Git服务,新建一个项目名叫CoreCICDTest,使用Git Push命令把本地代码推送上去。</p>
<h3 id="在阿里云容器镜像服务上新建项目并进行配置">在阿里云容器镜像服务上新建项目并进行配置</h3>
<p><img src="https://images.cnblogs.com/cnblogs_com/kklldog/1401672/o_TIM%E6%88%AA%E5%9B%BE20190805105613.jpg" alt="" loading="lazy"><br>
<img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805110039.jpg" alt="" loading="lazy"><br>
<em>点击“创建镜像仓库”按钮,弹出创建界面。填写命名空间kklldog,仓库名称cicd_test</em></p>
<p><img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805105736.jpg" alt="" loading="lazy"><br>
<em>点击下一步,代码源选择“本地仓库”,点击“创建镜像仓库”完成仓库的创建</em></p>
<h3 id="在阿里云codepipeline上新建项目并进行配置">在阿里云Codepipeline上新建项目并进行配置</h3>
<p><img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805110257.jpg" alt="" loading="lazy"><br>
<em>点击“新建”按钮跳转至新建项目页面。这个界面跟Jenkins简直就是一模一样</em></p>
<p><img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805110358.jpg" alt="" loading="lazy"><br>
<em>项目名称填写cicd_test,这里没有.net相关的模板,囧!项目类型选择"构建一个自由风格的软件"就可以</em><br>
<img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805110546.jpg" alt="" loading="lazy"><br>
<em>点击下一步,填写项目基本信息,源码选择Gitee。构建类型默认是java,无所谓不用过它</em><br>
<img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805110638.jpg" alt="" loading="lazy"><br>
<em>点击“绑定云码账号”跳转至云码授权页面进行授权,以便阿里云可以拉取云码上的代码</em><br>
<img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805110725.jpg" alt="" loading="lazy"><br>
<em>进行授权后,源码管理界面就可以选择到Gitee上的项目,填写相应的分支</em><br>
<img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805110819.jpg" alt="" loading="lazy"><br>
<em>点击“增加构建步骤”,选择“镜像构建与发布”</em><br>
<img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805110918.jpg" alt="" loading="lazy"><br>
<em>在“镜像构建与发布”界面填写刚才创建的仓库信息</em></p>
<pre><code>镜像仓库名格式为namespace/镜像仓库名。如果registry为Docker hub,拉取镜像命令为docker pull docker,则本配置项填写docker;如果 registry为阿里云Docker镜像仓库,拉取镜像命令为docker pull registry.cn-hangzhou.aliyuncs.com/acs-sample/wordpress, 则本配置项填写acs-sample/wordpress。
</code></pre>
<pre><code>Registry地址 用来配置docker registry地址,如果为空,默认使用Docker hub registry (https://index.docker.io/v1/);如果使用阿里云registry, 请填写https://registry.cn-beijing.aliyuncs.com/v2/,其中地域(cn-beijing)根据用户实际的镜像仓库地域来修改。
Registry证书 用来添加授权信息,请添加Registry授权类型的证书。
</code></pre>
<p><img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805111117.jpg" alt="" loading="lazy"><br>
<em>勾选“远程触发器”,先填写分支master,然后点击“生成”会生成触发器地址,这里好像有点小bug,有的时候这个地址不起效,如果不起效,多生成几次试试</em><br>
<img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805111152.jpg" alt="" loading="lazy"><br>
<em>在“构建后操作”界面填写邮件地址,用来接收邮件通知。勾选“每次不稳定的构建都发送邮件通知”</em></p>
<h3 id="在gitee的corecicdtest项目上配置webhook">在Gitee的CoreCICDTest项目上配置WebHook</h3>
<p><img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805111330.jpg" alt="" loading="lazy"><br>
<em>点击“管理&gt;WebHook”菜单,进行WebHook的配置</em><br>
<img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805111401.jpg" alt="" loading="lazy"><br>
<em>WebHook的Url填写刚才Codepipeline里的“远程触发器”里生成的url地址;密码不填;勾选Push事件,勾选“激活”;点击“添加”按钮完成Webhook的配置。这样当我们push代码的时候,Gitee会自动给配置的url发送一次post请求,里面携带了详细的项目信息,提交信息等数据</em><br>
<img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805111424.jpg" alt="" loading="lazy"><br>
<em>当点击“添加”按钮后Gitee会立马往webHook配置的url地址Post一次请求,如果Codepipeline做出“Task has been scheduled to queue”的响应则说明Codepipeline开始进行自动构建了</em></p>
<p><img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805113331.jpg" alt="" loading="lazy"><br>
<em>返回Codepipeline项目列表,可以看到cicd_test项目已经构建成功了</em><br>
<img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805113403.jpg" alt="" loading="lazy"><br>
<em>这个时候构建的镜像也应该被推送到了容器镜像服务的cicd_test仓库里。</em></p>
<h3 id="编写shell脚本运行容器">编写shell脚本运行容器</h3>
<pre><code>sudo vim publish_cicd_test.sh
输入以下内容
#!/bin/bash
sudo docker stop cicd_test
sudo docker rm cicd_test
sudo docker rmi registry-vpc.cn-shanghai.aliyuncs.com/kklldog/cicd_test
sudo docker login --username=xxx --password=xxx registry-vpc.cn-shanghai.aliyuncs.com
sudo docker pull registry-vpc.cn-shanghai.aliyuncs.com/kklldog/cicd_test:latest
sudo docker run --name cicd_test -d -p 7000:5000 -v /etc/localtime:/etc/localtime registry-vpc.cn-shanghai.aliyuncs.com/kklldog/cicd_test:latest
</code></pre>
<p><em>新建一个shell脚本命名为publish_cicd_test.sh;使用docker pull从仓库中拉取最近的镜像;使用docker run运行容器</em></p>
<pre><code>sudo /bin/bash publish_cicd_test.sh
</code></pre>
<p><img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805154305.jpg" alt="" loading="lazy"><br>
<em>运行一下shell脚本</em></p>
<pre><code>sudo docker ps -a
</code></pre>
<p><img src="https://images.cnblogs.com/cnblogs_com/kklldog/1401672/o_TIM%E6%88%AA%E5%9B%BE20190805163151.jpg" alt="" loading="lazy"></p>
<p><em>使用docker ps命令查看一下容器的运行状态,可以看到cicd_test容器已经运行成功了</em><br>
<img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805155639.jpg" alt="" loading="lazy"><br>
<em>使用浏览器访问一下对应的端口,网站已经正常运行了</em></p>
<h3 id="push代码触发构建">Push代码触发构建</h3>
<p>刚才的构建是我们配置Webhook的时候Gitee默认发送的一次请求,正常应该是用户使用git push命令后Gitee会发送一次请求,让我们模拟一下。<br>
<img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805160151.jpg" alt="" loading="lazy"><br>
<em>修改home/index页面,把V1.0改成V2.0</em><br>
提交成功之后查看Codepipeline项目列表,等待项目构建成功之后,我们再次运行一下publis_cicd_test.sh脚本,成功之后再次使用浏览器访问一下对应的端口看看home/index是否已经变为了V2.0<br>
<img src="https://www.cnblogs.com/images/cnblogs_com/kklldog/1401672/o_TIM%e6%88%aa%e5%9b%be20190805160417.jpg" alt="" loading="lazy"><br>
<em>可以看到home/index已经变成V2.0了,说明我们的持续集成流程跑通了</em></p>
<h2 id="持续交付部署">持续交付/部署</h2>
<p>我们上面演示的过程离一开始说的push一下代码就自动构建自动发布程序就差一点点了,太晚了下次再说吧。</p>


</div>
<div id="MySignature" role="contentinfo">
    <div id="AllanboltSignature">      
<p id="PSignature" style="border-top: #e0e0e0 1px dashed; border-right: #e0e0e0 1px dashed; border-bottom: #e0e0e0 1px dashed; border-left: #e0e0e0 1px dashed; padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; font-family: 微软雅黑; font-size: 11px">      
QQ群:1022985150 VX:kklldog 一起探讨学习.NET技术
<br>
作者:Agile.Zhou(kklldog)            
<br>
出处:http://www.cnblogs.com/kklldog/
<br>本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
</p>
</div><br><br>
来源:https://www.cnblogs.com/kklldog/p/core_in_docker_ci.html
頁: [1]
查看完整版本: .Net Core in Docker - 使用阿里云Codepipeline及阿里云容器镜像服务实现持续集成(CI)