使用 Jenkins 2.0 的 Pipeline 构建 微服务多项目的 Docker 项目发布

510 阅读1分钟

备份

docker export jenkins > jenkins.tar

安装

docker run -d --name jenkins \
	  -p 50000:50000 \
	  -p 7070:8080 \
	  -v /data/jenkins:/var/jenkins_home \
	  -v /var/run/docker.sock:/var/run/docker.sock \
	  -v /usr/bin/docker:/usr/bin/docker \
	  -v /root/.ssh:/root/.ssh \
	  -u root \
	  --restart always \
	  jenkinsci/blueocean

Account

http://xxx.xxx.xxx:7070/

admin
admin68Zt7zcR37ZbVChU

dev
dev

pipeline

#!groovy
// jenkins 的参数化构建 选项,在 Datadog Tagging 配置
Env_name = "${env_name}"
Tag_Preview_by_ops = ":preview_by_ops"
Dockerfile = '/Dockerfile '
Src = 'src/'
GroupURL = 'http://xxx.xxx.xxx:8082/new_mall/'
Group_SSH_URL = 'git@xxx.xxx.xxx:new_mall/'
GitLabCredentialsId = 'lingjie_gitlab'
DockerHubRegistry = 'http://localhost:5000/'

node {
timestamps {

    def BaseRepository = [
        'pb',
        'pkg',
        'xq'
    ] as List
    
    def ServerArray = [
        'backend_http_gate',
        'account',
        'product',
        'coupon',
        'order',
        'http_proxy',
        'mall',
        'money',
        'notice',
        'pay',
        'after_service',
        'recharge',
        'statistics',
    ] as List

    stage('prepare data dir'){
        BaseRepository.addAll(ServerArray)

        script{
            // https://blog.k4nz.com/63f9f5c157227d3c2f8a8cca18b3356c/
            // https://www.debugcn.com/article/22628704.html
            //todo 
            // sh 'docker cp /home/build_cache/ jenkins:/var/jenkins_home/workspace/pre_build/build'
        }

        script {
            build_file = "${env.WORKSPACE}/build"
            // build_file = "build"
            if(!fileExists(build_file)){
                error("build dir 不存在")
            }
        }
    }

    stage('parreller checkout source code'){
        def branche_name = ''
        switch(Env_name) {
            case 'prebuild':
                branche_name = '1.0.0'
                break
            // case 'prod':
            // //todo prod 分支 更新
            //     error('no over')
            //     break
        }

        dir(Src){
            def Map = BaseRepository.collectEntries {
                // def checkout_ext = [[$class: 'CleanCheckout'], [$class: 'CleanBeforeCheckout']] // calls git clean -fdx and git reset --hard

                [
                    "${it}" : {
                        checkout(
                            [
                                $class: 'GitSCM',
                                branches: [[name: "origin/" + branche_name]],
                                doGenerateSubmoduleConfigurations: false,
                                extensions: get_extensions(it),
                                submoduleCfg: [],
                                userRemoteConfigs: [
                                    [
                                        // credentialsId: GitLabCredentialsId,
                                        // url: 'http://xxx.xxx.xxx:8082/new_mall/' + it + '.git'
                                        // todo
                                        url: 'ssh://git@xxx.xxx.xxx:8082/new_mall/' + it + '.git'
                                    ]
                                ]
                            ]
                        )
                    }
                ]
            }

            parallel Map
        }
    }

    stage('checkout repo dockerfile') {
        dir('repo_dockerfile') {
            checkout(
                [
                    $class: 'GitSCM', branches: [[name: '*/master']],
                    userRemoteConfigs: [
                        // 运维机 gitlab
                        [url: 'ssh://git@xxx.xxx.xxx:11180/ops/dockerfiles.git']
                    ],
                ]
            )
        }

        parallel ServerArray.collectEntries {
            [
                "${it}" : {
                    sh('cp repo_dockerfile/' + "${it}" +  Dockerfile + ' ' + Src + "${it}" + Dockerfile)
                }  
            ]
        }
    }

    
    stage("配置文件环境替换") {
        // 源码签出后替换, 根据环境选择
		def _tar = '.tar'
        dir('env_config'){
            checkout(
                [
                    $class: 'GitSCM', branches: [[name: '*/'+ Env_name]],
                    userRemoteConfigs: [
                        [url: 'ssh://git@xxx.xxx.xxx:10022/ops/configs.git']
                    ],
                ]
            )

            parallel ServerArray.collectEntries {
                [
                    "${it}" : {
                        dir("${it}/app"){
							sh 'tar -cvf '+ "${it}" + _tar +' ./*'
							sh 'tar -xvf ' + "${it}" + _tar + ' -C '+ "${env.WORKSPACE}/" + 'src/' + "${it}/"
                        }
                    }
                ]
            }
        }
        
    }

    stage('build image'){
        // 不要使用
        // parallel ServerArray.collectEntries {  ["${it}" : gen_docker_build_stage(it)] }
        try {
            ServerArray.each({ item ->
                docker.withRegistry( DockerHubRegistry ) {
                    def image = docker.build(
                            DockerHubRegistry +'mall-'+ item + Tag_Preview_by_ops,
                            '-f src/' + item + Dockerfile + ' .'
                    )
                    image.push()
                }
            })
        } catch (Exception err) {
            throw err
            image_prune()
        } finally {}
    }

    stage('by ' + Env_name + 'env compose deploy up'){
        // 系统配置
        dingtalk (
            robot: 'dingding_robot',   
            type:'LINK', // TEXT
            atAll: false,
            title: "deplody",
            messageUrl: "${BUILD_URL}",
            text: ["deploy "+ Env_name + " ${BUILD_URL}\n" +"docker compose up"]
        )

        //todo
        //环境判断

        sh(
            //"ssh root@xxx.xxx.xxx 'pushd /home/data/project/ops_build_mall; docker-compose pull ; docker-compose up -d'"
            "ssh root@xxx.xxx.xxx 'pushd /home/data/project/ops_build_mall; docker-compose config;'  "
        )
    }

    stage('clean'){
        deleteDir()
        cleanWs()
        dir('src') {
            image_prune()
        }
    }
}
}// timestamps


def image_prune() {
   sh 'docker image prune -f'
}


def get_extensions(item) { 
    return [
                // 重命名目录
                [
                    $class: 'RelativeTargetDirectory', 
                    relativeTargetDir: item
                ],

                // git 浅拷贝
                [
                    $class: 'CloneOption', 
                    depth: 1, 
                    reference: '', 
                    shallow: true, 
                    timeout: 60
                ],
    ]
}


// todo 不要使用并行构建 很卡
def gen_docker_build_stage(job) {
    return {
        stage("${job}") {
            docker.withRegistry( DockerHubRegistry ) {
                def image = docker.build(
                        DockerHubRegistry + 'mall-' + "${job}" + Tag_Preview_by_ops,
                        "-f src/" + "${job}" + '/Dockerfile ' + ' .'
                )
                image.push()
            }
        }
    }
}

对接 gitlab api

    stage('http') {
            def response = httpRequest (
                contentType: 'APPLICATION_JSON',
                httpMode: 'GET',
                customHeaders: [
                    [
                        name: 'PRIVATE-TOKEN',
                        value: 'b-RY6yysoxksnssXNV3Q'
                    ]
                ],
                url: 'http://xxx.xxx.xxx:8082/api/v4/groups/8'
            )

            def props = readJSON text: response.content
            def projects =  props.projects

            for (project in projects) {
                //数组 add item
                ProjectNameArray << project.name
            }
            //def data = props['projects']

            // data.find{
            //     if(it.startsWith("b")){
            //         return true
            //     }
            //     return false
            // }

        //println data
    }

插件

thinBackup
SSH Pipeline Steps
Pipeline Utility Steps