zoukankan      html  css  js  c++  java
  • gitlab+docker+jenkins基于dockerfile持续集成

    篇幅使用的组件docker,dockerfile,docker-compose,registry,jenkins,gitlab,钉钉通知,篇幅有限,有些未详细写到的东西可能需要大家自行摸索。

    来介绍下这套自动发布的工作流程及搭建步骤,此文档只为记录及展示,为了篇幅不过长,docker,docker-compose,不做赘述,其余组件均使用docker运行,

    初始环境:

      IP1 : 192.168.18.221,jenkins+gitlab+docker-registry

      IP2:192.168.18.222,web

      关闭selinux

      关闭防火墙

    一,安装docker(两台机器都装)

    # step 1: 安装必要的一些系统工具
    yum install -y yum-utils device-mapper-persistent-data lvm2
    # Step 2: 添加软件源信息
    yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    # Step 3: 更新并安装Docker-CE
    yum makecache fast
    yum -y install docker-ce
    # Step 4: 开启Docker服务
    systemctl start docker      
    #这里还是添加下镜像加速
    vim /etc/docker/daemon.json

      {
      "registry-mirrors": ["https://8****lj0.mirror.aliyuncs.com"]
      }

    二,安装gtitlab

    # 不加 tag 则默认为最新版本 latest
    docker pull gitlab/gitlab-ce
    #通常会将 GitLab 的配置 (etc) 、 日志 (log) 、数据 (data) 放到容器之外, 便于日后升级, 因此请先准备这三个目录。
    mkdir -p /srv/gitlab/config
    mkdir -p /srv/gitlab/logs 
    mkdir -p /srv/gitlab/data
    #启动运行gitlab
    docker run --detach 
      --hostname gitlab.example.com 
      --publish 8443:443 --publish 8880:80 --publish 8222:22 
      --name gitlab 
      --restart always 
      --volume /srv/gitlab/config:/etc/gitlab 
      --volume /srv/gitlab/logs:/var/log/gitlab 
      --volume /srv/gitlab/data:/var/opt/gitlab 
     --add-host code.shiji.com:192.168.18.221 --privileged=true gitlab/gitlab-ce:latest
    #这里能成功访问后就不做额外的配置了,注意修改下配置文件里面的默认访问地址
    #配置下nginx代理后的访问地址 http://code.shiji.com (这里域名是使用的本地解析,当需要拉取代码的时候必须要能解析这个域名,)

    三,安装jenkins(这里放上官方文档  https://jenkins.io/zh/doc/pipeline/tour/deployment/)

    #拉取镜像(这里建议大家使用官方推介的镜像)
    docker pull  jenkinsci/blueocean:lts
    #创建挂载目录并修改权限
    mkdir /home/jenkins 
    #创建并运行 docker run -u root -d -p 8080:8080 -p 50000:50000 -v /home/jenkins:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock #如果需要在容器中运行docker命令,这条必须加上
    --add-host code.shiji.com:192.168.18.221 #这里我给jenkins添加了一条本地解析
     --restart always
    --name jenkins jenkinsci/blueocean:latest
    #在log中找到初始密码
    docker logs jenkins
    #修改密码后jenkins安装部分完成
    #访问地址,http://192.168.18.221:8080
    #备注,安装完成记得安装插件,这里用docker构建,需要安装 CloudBees Docker Build and Publish

    四,搭建registary私仓(需要把把代码用dockerfile构建后上传到私仓库,然后web服务器在拉下来重构,如果希望便捷操作可以使用云上的私人仓库)

    #拉取镜像
    docker pull registry
    #创建registry镜像存储目录
    mkdir -p /data/registry
    #创建启动registry
    docker run -d -p 5000:5000 --restart=always --name registry -v /data/registry:/var/lib/registry registry:latest
    #修改web服务的docker配置文件daemon.json,添加http
    vim /etc/docker/daemon.json
    {
     "insecure-registries": ["http://192.168.18.221:5000"],
      "registry-mirrors": ["https://8****lj0.mirror.aliyuncs.com"]
    }
    #构建完成后registry地址 http://192.168.18.221:5000

    五,配置持续集成,这里再次梳理下工作流程,开发人员提交代码  --> 触发gitlab钩子   --jenkins拉取代码构建  -->构建成功,推送镜像至私仓  -->web服务器拉取私仓镜像创建容器  -->通知用户;当然,失败的时候也会通知用户。

      1,配置pipeline,

        我们在jenkins里创建一个名为多分支的流水线,并且配置好代码仓,并且让他每次自动检出分支,以及检出前后都清理工作目录,其他选项使用默认即可,Build Configuration选择jenkinsfile;

        

         注意:此处配置完成后,scan流水线时会自动从gtilab里识别jenkinsfile文件,

      2,配置jenkinsfile文件,语法参考  https://jenkins.io/zh/doc/book/pipeline/,这里直接放出这边配置好的文件

    pipeline {
      agent any
      parameters {
    	 string(name:'BRANCH_FOR_BODY',defaultValue:"${BRANCH_NAME}",description:'parameters used by ding talk')     #此处的两个参数是为了后面钉钉通知的时候使用,这里后面再说
    	 string(name:'BUILD_URL_FOR_BODY',defaultValue:"${BUILD_URL}",description:'build uri for body')
      }
      stages {
        stage('Deploy-Production') {
          when {
            branch 'master'
          }
          steps {
            sh '''
             docker build -t ${DOCKER_IMAGE_NAME}:latest -f Dockerfile .                                      
            '''
            sh 'docker push ${DOCKER_IMAGE_NAME}:latest'      #这里选择每次都推送为lastest标签
            sh 'docker rmi ${DOCKER_IMAGE_NAME}:latest'    #同时删除本地构建打好标签的镜像
          }
          post {                       #根据执行标记来决定处理内容
            success {
    	      sh 'sh notice.sh "test生产环境镜像推送成功通知" "nginx-test" "推送镜像成功"  ${BRANCH_NAME} ${BUILD_URL}'     #此处的钉钉推送脚本最后会放出
            }
            failure{
    	      sh 'sh notice.sh "test生产环境镜像推送失败通知" "nginx-test" "推送镜像失败"  ${BRANCH_NAME} ${BUILD_URL}'
            }
          }
        }
      }
      environment {
        DOCKER_DEPLOY_URI = 'http://nginx.test.shiji.com'                    #这里只是为了个人使用,此篇幅未用到
        DOCKER_IMAGE_NAME = '192.168.18.221:5000/test/nginx-test'            #镜像名称
        DOCKER_SERVICE_NAME = 'TestService'                     #项目名称
      }
    }
    

      3,在上面的步骤中我们在构建的时候使用了dockerfile,这里使用个简单的nginx作为测试

    FROM nginx
    RUN echo 'This is the first version' > /usr/share/nginx/html/index.html
    

      4,接下来我们把dockerfile也上传至代码仓,这时构建当然是失败的,因为后续的钉钉通知脚本还没有上传,

      

      查看输出,可以看到镜像已经上传成功

      

       5,至此,持续构建算初步完成,放上钉钉推送信息的脚本,记得把tocken换成自己的,(注意新版本的钉钉机器人要加签了)

    gitAuthor=''
    gitAuthor=`git show --stat | awk '$0~/Author/{print $2}'`
    response=`curl -X POST -H 'Content-Type:application/json; charset=utf-8' 
    -d '{"msgtype":"markdown",
    "markdown":{"title":"'$1'",
    "text":"## '$1'
    
    **项目名称**:'$2'
    
    **提交人**:'$gitAuthor'
    
    **状态**:'$3'
    
    **分支**:'$4'\n\n有关更多构建的过程、错误信息、单元测试覆盖率报告请参照 [构建日志]('$5')"
    }}' https://oapi.dingtalk.com/robot/send?access_token=d7f17229b054200xxxxxxxxxxxxxxxxxxxx3204e4dee`
    echo $response
    

      6,gitlab自动推送,自动构建

        1,在jenkins安装gitlab插件,注意这里并不是哪个gitlabhook的插件

        

          &插件安装成功后我们修改jenkinsfile增加tigger,关于tigger的语法,官方文档和往上都给的不太详细,这里如果想过滤分支等操作参考下这两篇文章

          https://blog.51cto.com/ygqygq2/2461766

          http://www.eryajf.net/3298.html

          &放上修改完成的jenkinsfile   

    pipeline {
      agent any
      parameters {
    	 string(name:'BRANCH_FOR_BODY',defaultValue:"${BRANCH_NAME}",description:'parameters used by ding talk') 
    	 string(name:'BUILD_URL_FOR_BODY',defaultValue:"${BUILD_URL}",description:'build uri for body')
      }
      triggers{
    	gitlab( triggerOnPush: true,
    			triggerOnMergeRequest: true,
                branchFilterType: "NameBasedFilter",
    			includeBranchesSpec: "master,dev",
    			secretToken: "028d848ab64f"
    		)
      }
      stages {
        stage('Deploy-Production') {
          when {
            branch 'master'
          }
          steps {
            sh '''
             docker build -t ${DOCKER_IMAGE_NAME}:latest -f Dockerfile .                                   
            '''
            sh 'docker push ${DOCKER_IMAGE_NAME}:latest'
            sh 'docker rmi ${DOCKER_IMAGE_NAME}:latest'
          }
          post {  
            success {
    	      sh 'sh notice.sh "test生产环境镜像推送成功通知" "nginx-test" "推送镜像成功"  ${BRANCH_NAME} ${BUILD_URL}'
            }
            failure{
    	      sh 'sh notice.sh "test生产环境镜像推送失败通知" "nginx-test" "推送镜像失败"  ${BRANCH_NAME} ${BUILD_URL}'
            }
          }
        }
      }
      environment {
        DOCKER_DEPLOY_URI = 'http://nginx.test.shiji.com'
        DOCKER_IMAGE_NAME = '192.168.18.221:5000/test/nginx-test'
        DOCKER_SERVICE_NAME = 'TestService'
      }
    }

         2,jenkins设置里添加仓库(这里的tocken需要去gitlab里生成)

        

         3,gitlab项目里创建webhook

          

        4,最后提交一次测试效果(钉钉通知)

        

    7,到这里为止算是初步完成了自动构建,接下来要说说自动发布了,我们已经把镜像推送到了私仓,接下来只需要在应用服务器上执行命令构建就行,这里说说我们是怎么做的。

      应用服务器发布脚本,脚本使用compose发布,脚本执行也是放在Jenkins file里,(这里配置了两条是为了后续的pipeline多分支),脚本接受两个参数,一个名称及标签,标签是为了多分支的pipeline准备的,后续再说。

           脚本:

    tag="$2"
    # test
    if [ $1 == "test" ]
    then
    
        cd /docker/compose/test
        pwd
        docker pull 192.168.18.221:5000/test/nginx-test:$tag
    
        docker-compose up -d test
        echo "success"
    
    elif [ $1 == "test1" ]
    then
    
        cd /docker/compose/test1
        docker pull 192.168.18.221:5000/test/nginx-test:$tag
    
        docker-compose up -d test2
        echo "success"
    
    else 
        echo "no equal service"
    fi
    

      jenkinsfile:(写在setp阶段执行,这里我们使用的是接口的方式,需要在应用服务器上写个接口去执行上面的脚本,当然你也可以直接远程执行脚本,过程就不在赘述)

    steps {
            sh '''
             docker build -t ${DOCKER_IMAGE_NAME}:latest -f Dockerfile .                                   
            '''
            sh 'docker push ${DOCKER_IMAGE_NAME}:latest'
            sh 'docker rmi ${DOCKER_IMAGE_NAME}:latest'
         sh 'curl ${DOCKER_DEPLOY_URI}/staging?service=${DOCKER_SERVICE_NAME}' #请求接口去执行上面的脚本发布,接口怎么写的这里我就不放出来了,大家可以省略这一步直接远程执行脚本(要配置ssh互信)
    } 

    最后:多分支pipeline

      上面内容设置了一些变量,就是为此准备的,在这里我们可以对应环境分成多个流水线分支,主要还是修改jenkinsfile:

    pipeline {
      agent any
      parameters {
         string(name:'BRANCH_FOR_BODY',defaultValue:"${BRANCH_NAME}",description:'parameters used by ding talk') 
         string(name:'BUILD_URL_FOR_BODY',defaultValue:"${BUILD_URL}",description:'build uri for body')
      }
      triggers{
        gitlab( triggerOnPush: true,
                triggerOnMergeRequest: true,
                branchFilterType: "NameBasedFilter",
                includeBranchesSpec: "master,dev",
                secretToken: "028d848ab64f"
            )
      }
      stages {
        stage('Deploy-Production') {
          when {
            branch 'master'
          }
          steps {
            sh '''
             docker build -t ${DOCKER_IMAGE_NAME}:latest -f Dockerfile .                                   
            '''
            sh 'docker push ${DOCKER_IMAGE_NAME}:latest'
            sh 'docker rmi ${DOCKER_IMAGE_NAME}:latest'
            sh 'curl ${DOCKER_DEPLOY_URI}/staging?service=${DOCKER_SERVICE_NAME}&tags=latest'
          }
          post {  
            success {
              sh 'sh notice.sh "test生产环境镜像推送成功通知" "nginx-test" "推送镜像成功"  ${BRANCH_NAME} ${BUILD_URL}'
            }
            failure{
              sh 'sh notice.sh "test生产环境镜像推送失败通知" "nginx-test" "推送镜像失败"  ${BRANCH_NAME} ${BUILD_URL}'
            }
          }
        }
        stage('Deploy-Dev') {
          when {
            branch 'dev'
          }
          steps {
            sh '''
            docker build -t ${DOCKER_IMAGE_NAME}:dev -f Dockerfile .
            '''
            sh 'docker push ${DOCKER_IMAGE_NAME}:dev'
            sh 'docker rmi ${DOCKER_IMAGE_NAME}:dev'
            sh 'curl ${DOCKER_DEPLOY_URI}/dev?service=${DOCKER_SERVICE_NAME}&tags=dev'
          }
          post {
            success {
              sh 'sh notice.sh "test测试环境部署成功通知" "nginx-test" "成功"  ${BRANCH_NAME} ${BUILD_URL}'
            }
            failure{
              sh 'sh notice.sh "test测试环境部署失败通知" "nginx-test" "失败"  ${BRANCH_NAME} ${BUILD_URL}'
            }
          }
        } 
      }
      environment {
        DOCKER_DEPLOY_URI = 'http://dockerup.test.shiji.com'
        DOCKER_IMAGE_NAME = '192.168.18.221:5000/test/nginx-test'
        DOCKER_SERVICE_NAME = 'TestService'
      }
    }

      最后效果

        jenkins:

      

      钉钉通知:(这里在实际的生产环境中,并没有持续部署,所以通知是有区别的)

       

    写在最后:这篇是使用dockerfile的持续集成,当然还有其他方式,上面文中的连接作了更详细的讲解,各位看官如果能看到最后,欢迎留言指出文中不足的地方。

  • 相关阅读:
    解决Windows 7下IE11无法卸载、无法重新安装,提示安装了更新的IE版本
    [SQL Server] 数据库日志文件自动增长导致连接超时的分析
    DataTable转换为List<T>或者DataRow转换为T
    比较Js的substring、substr和C#的Substring
    .NET(c#)Parameters
    SheetJS保存Excel文件
    SheetJS将table转为Excel
    JS中使用let解决闭包
    Font Awesome图标的粗细
    滚动条样式修改
  • 原文地址:https://www.cnblogs.com/shiji888/p/12512136.html
Copyright © 2011-2022 走看看