Jenkins+Docker+SpringBoot持续集成流程说明
安装配置jenkins 安装jenkins可直接官网下载对应的jar包直接运行,也可使用docker运行,下载完后直接运行,并下载docker,jdk,maven等,并在jenkins->系统设置->全局工具配置里配置好对应的安装目录等。
配置全局凭据及应用服务器SSH 如果是使用私有代码仓库以及镜像仓库,则可以在全局配置里添加对应的用户名及密码,以便在jenkins配置脚本里引用。 jenkins->凭据->系统->全局凭据->添加凭据里添加对应仓库的登录账号以及密码,id(配置脚本引用时使用),描述等。
jenkins->系统管理->系统配置->Publish over SSH 模块里添加要执行部署脚本的应用服务器的登录用户密码等。
新建jenkins pipeline任务 在流水线模块,可点击流水线语法去生成对应的脚本(如git拉取代码,编译打包,push镜像,执行远程ssh脚本等)
项目引入dockerfile-maven-plugin插件 使用该插件将项目打包成docker镜像
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>${dockerfile.plugin.version}</version>
<configuration>
<repository>${project.artifactId}</repository>
<buildArgs>
<!-- 提供参数向Dockerfile传递 -->
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
项目目录下编写Dockerfile
FROM sapmachine/jdk11
VOLUME /tmp
# dockerfile-maven-plugin配置,即插件配置的<JAR_FILE>标签值
ARG JAR_FILE
# 将jar包添加到容器中并更名为app.jar
ADD ${JAR_FILE} app.jar
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo Asia/Shanghai >/etc/timezone
# 运行jar包
RUN bash -c "touch /app.jar"
EXPOSE 8080
# 以profile = prod 启动项目
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom","-Dspring.profiles.active=prod","-jar","/app.jar"]
jenkins pipeline脚本及部署脚本(可修改修改直接使用)
Jenkinsfile
node {
//构建版本的名称
def tag = "latest"
// 仓库私服地址
def docker_registry = "xxxxxxx"
// 命名空间
def docker_namespace = "mayfly"
// 项目名
def project_name = "test-xxx"
stage('拉取代码') {
// credentialsId:全局凭证的id url:git地址
git branch: 'master', credentialsId: 'git_test', url: 'https:git_project.git'
}
// 定义镜像名称
def imageName = "${project_name}:${tag}"
def tagName = "${docker_registry}/${docker_namespace}/${imageName}"
stage('编译,构建镜像') {
// 编译并安装公共工程
sh "mvn clean -Dmaven.test.skip=true install"
// 编译,并使用dockerfile-maven-plugin插件命令构建本地镜像
sh "mvn -f ${project_name} clean package -Dmaven.test.skip=true dockerfile:build"
}
stage("发布镜像至仓库") {
// 给镜像打标签
sh "docker tag ${imageName} ${tagName}"
withCredentials([usernamePassword(credentialsId: 'docker_repo', passwordVariable: 'password', usernameVariable: 'username')]) {
// 登录
sh "docker login -u ${username} -p ${password} ${docker_registry}"
// 上传镜像
sh "docker push ${tagName}"
}
// 删除本地镜像
sh "docker rmi -f ${imageName}"
sh "docker rmi -f ${tagName}"
}
stage("服务器执行部署脚本") {
// execCommand: 执行部署脚本命令及传递参数
sshPublisher(publishers: [sshPublisherDesc(configName: 'eatlife-server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/usr/local/java/deploy.sh $docker_registry $docker_namespace $project_name $tag", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '\'\'')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
deploy.sh
#! /bin/sh
#接收外部参数,由jenkinsfile执行部署脚本时传递
docker_registry=$1
docker_namespace=$2
project_name=$3
tag=$4
imageName=$docker_registry/$docker_namespace/$project_name:$tag
echo "镜像名: $imageName"
echo "项目名: $project_name"
#查询容器是否存在,存在则删除
containerId=$(docker ps -a | grep -w "${project_name}":"${tag}" | awk '{print $1}')
if [ "$containerId" != "" ] ;
then
#停掉容器
docker stop "$containerId"
#删除容器
docker rm "$containerId"
echo "成功删除容器"
fi
#查询镜像是否存在,存在则删除
imageId=$(docker images | grep -w "$project_name" | awk '{print $3}')
if [ "$imageId" != "" ] ;
then
#删除镜像
docker rmi -f "$imageId"
echo "成功删除镜像"
fi
# 登录docker私服
docker login -u user -p pwd "$docker_registry"
# 下载镜像
docker pull "$imageName"
# 启动容器,指定网络并暴露80端口
docker run -itd --name "$project_name" --network mayfly-net -p80:8080 "$imageName"
echo "容器启动成功"