gitlab+docker+jenkins基于dockerfile持续集成

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

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

初始环境:nginx

  IP1 : 192.168.18.221,jenkins+gitlab+docker-registrygit

  IP2:192.168.18.222,webweb

  关闭selinuxdocker

  关闭防火墙json

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

# 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"]
  }centos

二,安装gtitlabapi

# 不加 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'\n\n**项目名称**:'$2'\n\n**提交人**:'$gitAuthor'\n\n**状态**:'$3'\n\n**分支**:'$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的持续集成,固然还有其余方式,上面文中的链接做了更详细的讲解,各位看官若是能看到最后,欢迎留言指出文中不足的地方。