jenkins使用腾讯云容器镜像服务

280 阅读3分钟

过去我们都是使用自己搭建的harbor私有镜像仓库,基本上还算流畅,也出现过几次问题:域名证书过期、服务器磁盘满了、服务器带宽不够,主要是带宽不够这个问题,镜像文件太大了就造成速度慢甚至超时。

后来知道腾讯云有容器镜像服务,原打算让公司花2w买三年企业版,但是呢一直没得到支持,查文档看到个人免费版是可以推100个镜像,而且会自动清理,那就满足我们需求了。

进入腾讯云管理控制台,找到 容器镜像服务

image.png

已经新建 cyrjhub,以后所有项目都用这个命名控件即可

image.png

回到jenkins里面在全局凭据中添加 腾讯云镜像仓库账号密码

image.png

以前端sci-web为例,同原来自建Harbor,只有改三个地方:新地址、命名控件和凭据ID,这三个地方在以后项目中都是固定的用这三个即可

1、  harborServer、harborInnerSite  这两个其实可只用一个了,可以去掉harborInnerSite,都用harborServer,以前是因为自己搭建的harbar仓库,带宽限制做了内外网优化

2、 harborLibrary  这里是固定 chub,上面在腾讯云控制台建的命名空间

3、  tengx_docker_personal  有两处用到,一是jenkins服务器上push镜像,二是目标服务器pull镜像,这个名字是上面全局凭据自己写的ID名称

// 注意先建system凭据

pipeline {
  agent any
	
	  environment {
        // 毫秒做镜像标签
        imageTag = sh(script: "echo `date '+%Y%m%d%H%M%S'`", returnStdout: true).trim()
        // harbor仓库
        harborServer = 'ccr.ccs.tencentyun.com' // 腾讯云固定
        harborLibrary = 'chub'  // 腾讯云固定用这个
        // git项目
        gitServer = 'http://xxx.xxx.xxx.xxx:30300/'  // 可以修改,git仓库地址
        gitGroup = 'root'               // 可以修改,git里面项目分组名
        gitProjectName = 'jeecg-nest-server'   // 可以修改,git项目名称
        // 后端接口,区分开测试环境和生产环境
        testApiServer = 'http://172.16.0.xxx'  // 测试服务器内网ip
        proApiServer = 'http://172.17.0.xxx'  // 生产服务器内网ip
        // 服务器ssh地址
        testSshServer = 'xxx.xxx.xxx.xxx'     // 测试服务器外网ip
        proSshServer = 'xxx.xxx.xxx.xxx'      // 生产服务器外网ip     
    }
    
    parameters {
        // gitParameter name:'MR_TO_BRANCH',
        //              type:'PT_BRANCH_TAG',
        //              branchFilter:'origin/(.*)',
        //              defaultValue:'dev',
        //              selectedValue:'DEFAULT',
        //              sortMode:'DESCENDING_SMART',
        //              description:'选择分支'
        choice(
          choices: "test\npro", name:'buildType', description:'选择发布环境,test服119,pro服195'
        )
        // string( name: 'MR_TO_BRANCH', defaultValue: 'master', description: '输入分支', trim: true)
        choice(
          choices: "master\ndev\nnewui\ntest-template\ntest-sentry", name:'MR_TO_BRANCH', description:'输入分支'
        )
        choice(
          choices: "3001", name:'apiDokerPort', description:'nest后端发布端口'
        )
    }
	
    stages {
        stage('拉取代码') {
            steps {
                script {
                  if(params.buildType == 'test'){
                    env.apiServer = "${env.testApiServer}:${apiDokerPort}"
                    env.sshServer = env.testSshServer
                    env.sshPort = 22
                  }
                  if(params.buildType == 'pro'){
                    env.apiServer = "${env.proApiServer}:${apiDokerPort}"
                    env.sshServer = env.proSshServer
                    env.sshPort = 12358
                  }
                  env.dockerImageName = "${gitProjectName}_${buildType}_${apiDokerPort}"
                }
                git branch: "${MR_TO_BRANCH}",credentialsId: 'gitlabroot', url: "${gitServer}/${gitGroup}/${gitProjectName}.git"
            }
        }
        stage('代码构建') {
            steps {
                script{
                  sh '''
                     npm install --force
                     npm run build
                  '''
                }
            }
        }
        stage('打包docker') {
            steps {
                script{
                  sh '''
                      docker build -t ${harborServer}/${harborLibrary}/${dockerImageName}:${imageTag} .
                  '''
                }
            }
        }
        stage('推送镜像') {
            steps {
                script{
                    withCredentials([usernamePassword(credentialsId: 'tengx_docker_personal', passwordVariable: 'harbor_password', usernameVariable: 'harbor_username')]) {
                        sh '''
                            docker login -u ${harbor_username} -p ${harbor_password} ${harborServer}
                            docker push ${harborServer}/${harborLibrary}/${dockerImageName}:${imageTag}
    				            '''
                    }
                }
            }
        }
        stage('清理镜像') {
            steps {
                script{
                  catchError(buildResult:'SUCCESS', stageResult:'SUCCESS'){
                    // 1、清理当前镜像  2、清理2天前历史缓存中间镜像
                    sh '''
                      docker rmi -f ${harborServer}/${harborLibrary}/${dockerImageName}:${imageTag}
                      docker images -f "dangling=true" '--format={{.Tag}} {{.ID}} {{.CreatedAt}}' | awk '{CS=mktime(sprintf("%s %s %s 00 00 00",substr($3,0,4),substr($3,6,2),substr($3,9,2)));ID=$2;NS=systime();DT=NS-2*86400;if(DT > CS){print ID}}' | xargs -r docker rmi -f
                    '''
                    // 不移除空白的镜像,因为那些是docker分层缓存 2023.09.08
                    // docker rmi -f $(docker images | grep "none" | awk '{print $3}')
                    // docker自带清理缓存10天前
                    // docker builder prune --filter  'until=240h' -f
                  }
                }
            }
        }
        stage('部署') {
            steps {
                script{
                  // 测试环境要打包+发布;生成环境只打包
                  withCredentials([usernamePassword(credentialsId: 'tengx_docker_personal', passwordVariable: 'harbor_password', usernameVariable: 'harbor_username')]) {
                      sh '''
                          SSHCMD="
                            docker login -u ${harbor_username} -p ${harbor_password} ${harborServer}; 
                            docker pull ${harborServer}/${harborLibrary}/${dockerImageName}:${imageTag}; 
                            docker ps -a --filter 'name=${dockerImageName}' -aq | xargs -r docker rm -f; 
                            docker images | grep '${dockerImageName}' | grep -nv '${imageTag}' | awk '{print $3}'| xargs -r docker rmi -f; 
                            docker run -d --restart always --name ${dockerImageName} -v /home/${dockerImageName}/db/:/app/db/ -p ${apiDokerPort}:3000 ${harborServer}/${harborLibrary}/${dockerImageName}:${imageTag}; 
                          "
                          ssh -p ${sshPort} root@${sshServer} ${SSHCMD}
                      '''
                  }
                }
            }
        }
        // stage('清理腾讯云') {
        //     steps {
        //         script{
        //           sh '''
        //               sleep 1
        //               sh /var/jenkins_home/workspace/DeleteImagePersonal.sh ${harborLibrary}/${dockerImageName} ${imageTag}
        //           '''
        //         }
        //     }
        // }
        stage('打印结果') {
            steps {
              script {
                echo "本次构建 ${params.buildType} 完成:"
                echo "镜像名:${harborServer}/${harborLibrary}/${gitProjectName}_${params.buildType}_${apiDokerPort}:${imageTag}"
                echo "接口地址: ${apiServer}"
                echo "页面地址: http://${sshServer}:${apiDokerPort}"
                echo "容器端口: ${apiDokerPort}"
              }
            }
        }
    }
}