CI/CD

CI/CD

啥是CI/CD

CI: continuous integration, 持续集成。就是频繁地把开发的工作提交到主线代码。主要是为了解决集成问题。什么是集成问题呢,白话说,就是从你本地的代码pull下来的时间点开始,距离你提交时候越长,你提交时候遇到冲突的风险越大。因为别人也可能会修改。

CD: continuous delivery, 持续交付。简言之就是频繁地经过UT、静态代码分析、build过程产出release。

CD:continuous deployment, 持续部署。拿到持续交付的产出(release),自动化部署到环境,并经过自动化测试过程。

实现举例

最近项目基于Jenkins, Docker实现CI/CD,在此记录一下。

jenkins 安装

wget http://mirrors.jenkins.io/war-stable/latest/jenkins.war
java -jar jenkins.war --httpPort=8889 >./jenkins.log &

#初始化Jenkins时需要的密码
cat ~/.jenkins/secrets/initialAdminPassword

#安装推荐的plugin
#创建Admin

在Manage Jenkins->Global Tool Configuration->Add Maven 添加一个叫M3的Maven,自动安装maven,下面pipeline脚本会用(可选,如果没此步自己要先安装好maven)

jenkins任务的配置主要是通过页面完成。

点击New Item,输入名字,选择Pipeline,点OK

General里配置一些项目描述信息

Build Triggers设置编译触发。比如勾选Build periodically表示定期编译。Schedule填写H 5,10,15,20,23 * * *表示每天的5点、10点、15点、20点和23点都编译一次。而选择Poll SCM表示有提交才编译。

Pipeline里配置pipeline脚本。(这里用我自己git的一个小项目)

node {
  def mvnHome
  stage('Preparation') {
    git 'https://github.com/qwsdcv/Stock.git'
    mvnHome = tool 'M3'
  }
  stage('Build') {
    sh "'${mvnHome}/bin/mvn' -f SpringStuff/pom.xml -Dmaven.test.failure.ignore clean package"
  }
  stage('Results') {
    //junit '**/target/surefire-reports/TEST-*.xml'
    //archive 'SpringStuff/target/*.jar'

    def date = sh (script: 'date +"%Y%m%d-%H%M%S"',returnStdout: true).trim()
    
    def RELEASEDIR = "~/release/${date}"
    
    def mkdir = { dir->
        sh "mkdir -p ${dir}"
    }
    mkdir(RELEASEDIR)

    sh "cp SpringStuff/target/*.war ${RELEASEDIR}"
  }
}

docker

我们的Dockerfile
从一个公共的image jetty开始,把生成的war包拷贝进去

FROM jetty

COPY SpringStuff/target/*.war /var/lib/jetty/webapps

那上面的pipeline脚本就可以改成下面这样了

node {
  def mvnHome
  stage('Preparation') {
    git 'https://github.com/qwsdcv/Stock.git'
    mvnHome = tool 'M3'
  }
  stage('Build') {
    sh "'${mvnHome}/bin/mvn' -f SpringStuff/pom.xml -Dmaven.test.failure.ignore clean package"
  }
  stage('Results') {
    //junit '**/target/surefire-reports/TEST-*.xml'
    //archive 'SpringStuff/target/*.jar'

    def date = sh (script: 'date +"%Y%m%d-%H%M%S"',returnStdout: true).trim()
    
    def RELEASEDIR = "~/release/${date}"
    
    def mkdir = { dir->
        sh "mkdir -p ${dir}"
    }
    mkdir(RELEASEDIR)

    sh "cp SpringStuff/target/*.war ${RELEASEDIR}"
    //这里我可以直接build 是因为我把Dockerfile上传到github的根路径下了
    sh "docker build -t jetty_stock_${date} ./"
    
  }
}

结合docker-registry搭建一个私有仓库,每次build完成打个标签推送到私有仓库就OK啦。

后面我会写一个用来申请容器环境的web服务。

另外附加这些指令解释

#生成image
docker build -t jetty_stock ./ 
#运行容器, 把容器内部的8080端口映射到宿主机器的9000端口
docker run -d -p 9000:8080 jetty_stock
docker ps #列出正在运行的容器
docker ps -a #列出所有容器,包括停了的
docker stop XXXX #停止容器
docker rm XXXX #删除容器(需要先停止再删除)

docker images #列出所有镜像
docker rmi XXX #删除镜像

docker rm `docker ps -a -q` #删除所有容器
posted @ 2018-06-22 18:10  开学五年级了  阅读(267)  评论(0编辑  收藏  举报