项目背景
一个典型的 Spring boot 微服务项目,项目目录大概是这样子
项目包含公共模块和多个微服务模块,现在需要用 Jenkins 构建多个微服务的 Docker 镜像并推送到私有镜像仓库。
Jenkins 构建任务配置
配置好的构建任务,构建面板是这样的
部分关键配置参考
比较关键的是上图这一部分定义了两个变量,构建脚本里会取这两个变量的值
branch
拉取代码的 git 分支project_name
选择的要构建的微服务,value 部分配置的是微服务名称@端口
Jenkins 构建脚本放在了项目根目录下。
Jenkins 构建脚本参考
// git凭证ID
def git_auth="aaaaaaaaaaaaaaaa"
// git地址
def git_url="https://gitlab.demo.com/zy/demo.git"
// tag标签版本
def tag="latest"
// harbor地址
def harbor_url="harbor.demo.com"
// harbor项目名称
def harbor_project_name="library"
// harbor凭证id
def harbor_auth_id="bbbbbbbbbbbbbbbb"
node {
// 把选择的项目信息转为数组
def selectedProjects = "${project_name}".split(',')
stage('拉取代码') {
checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
}
stage('编译,安装公共子工程') {
sh "mvn clean install"
}
stage('编译,打包,推送镜像,构建镜像'){
for(int i=0;i<selectedProjects.size();i++){
// 取出每个项目的名称和端口
def currentProject = selectedProjects[i];
// 项目名称
def currentProjectName = currentProject.split('@')[0]
// 项目启动端口
def currentProjectPort = currentProject.split('@')[1]
// 定义镜像名称
def imageName = "mcu-${currentProjectName}:${tag}"
// 编译,构建本地镜像
sh "mvn -f ${currentProjectName} clean package "
// 判断名称是否包含父目录
if(currentProjectName.contains("/")){
currentProjectName=currentProjectName.split("/")[currentProjectName.split("/").size()-1]
imageName = "mcu-${currentProjectName}:${tag}"
}
// 给镜像打标签
sh "docker build -t ${harbor_url}/library/${imageName} ./${currentProjectName}/"
// 把镜像推送到harbor
withCredentials([usernamePassword(credentialsId: "${harbor_auth_id}", passwordVariable: 'password', usernameVariable: 'username')]) {
// 登录harbor
sh "docker login -u ${username} -p ${password} ${harbor_url}"
// 上传镜像
sh "docker push ${harbor_url}/library/${imageName}"
}
// 删除本地镜像
sh "docker rmi -f ${harbor_url}/library/${imageName}"
echo "${currentProjectName}完成编译,构建镜像"
}
}
}