Asp.net Core 使用Jenkins + Dockor 实现持续集成、自动化部署(
写在前面我们以前windows跑.net Framework程序的时候,发布,自己乖乖的替换程序;备份,也是自己一个一个的重命名备份;回滚,发布遇到问题的回滚更是不用说了;运维很是怕我们 这些用windows的啊; 那全面拥抱linux的一一.net core 时代 ,是如何处理这些个问题的呢? 噔噔蹬蹬~请往下看。 运行环境centos:7.2 Jenkins ver. 2.150.1 一台安装jenkins的机器。
背景我们目前的应用部署环境是这样划分的(暂定): 开发环境环境变量:Development 开发环境就是我们平时的开发用的机器,错误、异常尽可能多的报出来这种。css、js、页面文件等各种静态资源也不做压缩处理,连接测试库; 开发环境的部署:开发人员按自己习惯自己部署; 测试环境环境变量:Staging 测试环境也就是测试同学测试用的环境,为了贴合生产环境的多机器部署,我们测试机器也有多台,目前我们搭建了jenkins可由测试同学自己部署;错误信息已做捕捉处理,静态文件同样不压缩,连接测试库; 测试环境的部署:docker+docker-compose部署,我们在项目里面编写好了Staging.Dockerfile、docker-compose.yml还有对应的测试环境发布的shell脚本,借助jenkins来进行参数化的构建。参数包括程序运行的端口、绑定的ip,consul配置等等。哦对了,我们目前的构建步骤大概是:
预生产环境环境变量:Staging 预生产环境是相对于测试环境来说,无论数据、配置还是架构都是更加接近生产环境的存在了。一般还是连接的数据库是预生产环境的数据库(同步了生产环境的数据的),甚至有的使用会直接连接生产环境的库(一般不练、只读账号等控制);不过我们公司还是连接的测试库 然后静态文件压缩啊、什么的这些,生产环境怎么处理,这里也怎么处理; 通过测试环境测试的程序才可以部署到这里,这里测试通过后,才可以部署到生产环境; 预生产环境的部署:由项目负责人或者运维部署,需要比较大权限才可以; 生产环境环境变量:Production 生产环境一般应配置为最大限度地提高安全性、性能和应用可靠性,包括但不限于以下举措:
生产环境的部署:运维部署,我们开发没有权限了; 部署的背景我们的条件等等大概讲完了,下面我们说说生产环境我们怎么设计容器的。 生产环境的容器设计由于生产环境经常需要修改配置、保留日志信息、需考虑程序的备份与回滚等等,我们不能像上面的测试环境一样,把整个发布的产品打包成一个镜像了,我们需要做特殊的处理; 熟悉docker的同学,肯定会想到:挂载 对的,我们就这么处理,我们用docker -v 处理这头痛的问题; 程序的目录结构我们程序的目录结构是这样的: backs:放历史版本的程序文件,按备份日期压缩命名; logs:程序的运行日志文件; program:当前运行的程序;
backs目录截图: 发布发布步骤
发布脚本(Production.Publish.sh)#!/bin/bash function success() { echo -e " 33[32m $1 33[0m" } function error() { echo -e " 33[31m 33[01m $1 33[0m" } echo "publish beging。。。。。。" remotePath=$1 healthCheckUrl=$2 defaulPaht= $3; bashPath=${defaulPaht:=`pwd`} if [ ! $remotePath ]; then echo "warn:remotePath should't be empty!" exit fi if [ ! $bashPath ]; then error "error:bashPath should't be empty!" exit fi echo "bashpath is ${bashPath}" programPath="${bashPath}/program" logPath="${bashPath}/logs" backPath="${bashPath}/backs" publisTemp="${bashPath}/publisTemp" mkdir -p $programPath mkdir -p $logPath mkdir -p $backPath mkdir -p $publisTemp #remote git or scp #这里同步预生产环境的程序文件,这里写死了ip只是示例,scp也只是示例 #大家可以采用更安全,更有效率的同步文件方式 scp -r [email?protected]:${remotePath}"/.*" ${publisTemp} if [ $? ]; then echo "info:copy successful!" #压缩、备份当前运行程序到backs文件夹 backFileName=`date +%Y%m%d%H%M%S`".tar.gz" `cd ${programPath} && tar -zcPf ${backPath}/${backFileName} *` #replace #替换程序 if [ $? ]; then mv $programPath ${programPath}"Old" mv $publisTemp ${programPath} rm -r ${programPath}"Old" #publis fail ,then Production.Rollback if [ $healthCheckUrl ]; then curl $healthCheckUrl if [ $? -ne 0 ]; then error "error:public failed!" #心跳检测失败,执行回滚 if [ -f "Production.Rollback.sh" ];then echo "************************************ exec Rollbacking...... ************************************" ./Production.Rollback.sh ${backPath} else error "error:Production.Rollback.sh is not existing!"; fi exit fi fi success "publish Successful!" else error "error:file tar failed!" fi else error "error:remote files copy failed,Maybe you should checkout your ssh auth!" fi DockerfileDockerfile比较简单 FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base WORKDIR /app ARG RUN_PORT=${RUN_PORT:-""} ARG CONSUL_TO_NETCOREHOST=${CONSUL_TO_NETCOREHOST:-""} ARG ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT:-""} ENV RUN_PORT=${RUN_PORT} CONSUL_TO_NETCOREHOST=${CONSUL_TO_NETCOREHOST} ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT} ENTRYPOINT ["dotnet","Member.WebApi.dll"] docker-composeversion: '3.4' services: member.webapi: image: memberwebapi${RUN_PORT} build: context: . dockerfile: ${ASPNETCORE_ENVIRONMENT}.Dockerfile network_mode: "host" restart: always environment: - RUN_PORT=${RUN_PORT} - ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT} - CONSUL_TO_NETCOREHOST=${CONSUL_TO_NETCOREHOST} command: - "--port" - "${RUN_PORT}" #就是这里挂载 volumes: - ../program/:/app/ - ../logs/:/app/logs 回滚回滚其实就是发布的逆操作; 发布是:同步最新程序->备份当前运行程序->替换; 回滚是->找到上一次的备份->删掉的当前运行程序->替换; Production.Rollback.sh#!/bin/bash echo "rollback beging。。。。。。" defaulPaht= $1; bashPath=${defaulPaht:=`pwd`} programPath="${bashPath}/program" backPath="${bashPath}/backs" lastFile=`cd ${backPath} &&ls -t |head -n1|awk '{print $0}'` if [ ! $lastFile ];then echo "error:none backup program!" fi lastFilePath="${backPath}/${lastFile}" echo $lastFilePath if [ -f $lastFilePath ];then echo "rollback program:${lastFilePath}" programOldPath="${programPath}Old" mkdir -p ${programOldPath} tar zxvf ${lastFilePath} -C ${programOldPath} #replace if [ $? ]; then rm -r ${programPath} mv ${programOldPath} ${programPath} echo "rollback Successful!" else echo "error:backup program is not existing!" fi else echo "error:backup program is not existing!" fi 最后贴一个运行截图: 总结毫不夸张地说,Jenkins + Dockor 让.net 完全从一个刀耕火种的原始人一下子穿越到了全自动化的现代; 文章的思路可以借鉴,脚本改改也可以用,但需理解思路; 有的同学可能会问,为什么生产环境的部署,不能像测试环境一样直接拉取master的代码构建,我这里的回答是涉及到配置的权限问题、devops的学习到位问题。历史原因等,我们暂定这样,后面实践,我乐于分享; 本文的实践都有很大的局限性,比如有现成的工具、有更强大的插件等等可以更简单的去解决这个问题之类的,我可能还不知道;比如我的shell写的一塌糊涂等等。。欢迎沟通,不理赐教。 晚安~ (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net-web-api – 在Webapi中使用Url.Link与属性路由2
- asp.net-mvc – ASP.NET MVC模型绑定外键关系
- 加速ASP.NET开发
- asp.net – 跨页回发并再次保留源页面中的数据
- asp.net-mvc – HtmlHelper NameFor方法
- asp.net-mvc-4 – Resharper无法解析主页中的部分视图
- 浅析微软的网关项目 -- ReverseProxy
- asp.net-mvc-3 – ASP.NET MVC 3 Razor查看onclick编码
- asp.net网站的“网站正在建设中”页面
- asp.net-mvc – 异步HttpModule MVC