通过 Nuke 为 Dotnet Core 应用构建自动化流程

笔记哥 / 05-12 / 20点赞 / 0评论 / 841阅读
## 为什么使用Nuke 最开始了解Nuke,是浏览github时,刷到了这个项目,看简介可以通过C# 来定义构建任务和流程,这一点很新颖,对我来讲,c# 显然更容易理解和维护。 再看给出的示例,确实比较清晰,简洁。看了下官方文档,也提供了大量第三方CLI的支持,工具支持比较好,也就是可以使用C#方法调用,代替直接使用cli 命令。 还可以与 gitlab jenkins 结合,实现CI、CD,兼容windows 与 linux。 看文档介绍,是不错的,对于缺少运维人员的团队,可以尝试使用。 ![](https://cdn.res.knowhub.vip/c/2505/12/3e88294b.jpg?G1cAAMTW3Dgp8IJm22gD1Vl6p82ARRpBpYT1uvee6yR6PgdD4%2fW3Pnx9%2bE3rwwnFuJZKYBgbQhCIJraa9QhiViQhZ43vdA%3d%3d) ## 示例场景 1. 为同一个解决方案下的多个Dotnet Core 项目构建dokcer镜像 2. 使用Gitversion的版本策略,生成镜像标签 3. 并推送至镜像仓库  逻辑比较简单,可以拆分为,通过 gitversion 生成版本号,通过docker build 生成镜像,以及通过docker push 推送镜像。 ## Nuke 初始化 按需安装Nuke 版本,以及在项目跟目录下,进行初始化。 ```csharp dotnet tool install Nuke.GlobalTool --globalnuke :setup ``` ## 调整构建流程 通过 LoginDocker 实现了登录docker镜像仓库; 通过 BuildDockerImages 实现了多个项目的镜像构建,并采用 GitVersion 的 FullSemVer 作为版本号,构建时启用了DOCKER\_BUILDKIT; 通过 PushImages 实现了镜像推送; 通过 CleanImages 清除本地镜像; ```csharp using System; using System.Collections.Generic; using System.Linq; using Nuke.Common; using Nuke.Common.ProjectModel; using Nuke.Common.Tooling; using Nuke.Common.Tools.Docker; using Nuke.Common.Tools.GitVersion; using Serilog; using static Nuke.Common.IO.FileSystemTasks; using static Nuke.Common.Tools.Docker.DockerTasks; class Build : NukeBuild { [GitVersion] readonly GitVersion GitVersion; [Solution] readonly Solution Solution; [Parameter(Name = "proj")] readonly string ProjectName; public Build() { DockerLogger = (s, e) => Log.Debug(e); } public static int Main() => Execute(x => x.RunDockerTasks); string RegistryUrl => "registry.mydomain.com"; string ImagePrefix => $"{RegistryUrl}/products"; IEnumerable Projects => Solution.AllProjects.Where(p => p.Name.EndWith("Host")); readonly List localImages = new(); Target LoginDocker => _ => _ .Executes(() => { DockerLogin(_ => _ .SetServer(RegistryUrl) .SetUsername("xxx") .SetPassword("xxxxx")); }); Target BuildDockerImages => _ => _ .Executes(() => { foreach (var project in Projects) { var tag = $"{ImagePrefix}{project.Name}:{GitVersion.FullSemVer}"; localImages.Add(tag); DockerBuild(_ => _ .SetProcessEnvironmentVariable("DOCKER_BUILDKIT", "1") .SetPath(“./”) .SetFile(project.Directory / "Dockerfile") .SetTag(tag)); } }); Target PushImages => _ => _ .DependsOn(BuildDockerImages) .DependsOn(LoginDocker) .Executes(() => { foreach (var image in localImages) { DockerPush(_ => _.SetName(image)); } }); Target CleanImages => _ => _ .DependsOn(PushImages) .Executes(() => { foreach (var image in localImages) { DockerImageRm(s => s .SetImages(image) .SetForce(true)); } }); Target RunDockerTasks => _ => _ .DependsOn(CleanImages) .Executes(() => { Serilog.Log.Information($"{ProjectName} 构建结束"); }); } ``` ## 调试 本地运行代码,既可以执行以上逻辑,以及调试;非常方便。 ## 调用 通过 执行命令行:dotnet nuke RunDockerTasks 即可执行镜像的构建与推送,可以很方便的与gitlab、github、jenkins 等结合。 ![](https://cdn.res.knowhub.vip/c/2505/12/52f60106.png?G1YAAMT0bJxoHUptox%2f6n3gkNAMSWQSVEtbrvXefRvT9Bkbyz%2bxj2fnwlz6WEUpmLUpgZM5wPiBIqFErw4kkjZIYfk8D) ## 优化 1. 执行以上CI,需要宿主机,安装Dotnet SDK,以实现 Dotnet tools 的安装,以及Docker 客户端的安装;可以考虑使用Docker In Docker的方式,减少对服务器的要求; 2. 默认会对所有的项目进行构建并推送,可以结合 Parameter 的方式,按需指定需构建的项目; 3. 可以使用compose 方式构建,隐藏项目细节; ## 总结 对于功能不复杂、脚本不熟悉、或者缺少运维的场景下,可以尝试使用。