jenkins部署springboot项目,打包为docker镜像

一、集成工具下载

JDK

最新版jdk内置版本为11,如需要兼容jdk8请参考我上一篇文章

jdk11版本jenkins打包jdk8项目,同时兼容jdk11与jdk8

编译工具

gradle

image-20221016151018290

maven

image-20221016151054984

二、springboot项目docker打包支持

gradle项目

gradle脚本配置docker插件

buildscript {
	ext {
		springBootVersion = '2.3.12.RELEASE'
	}
	repositories {
		maven { url "https://maven.aliyun.com/nexus/content/groups/public/" }
		mavenCentral()
		maven { url "https://repo.spring.io/snapshot" }
		maven { url "https://repo.spring.io/milestone" }
	}
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
		classpath("se.transmode.gradle:gradle-docker:1.2")
	}
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'idea'
apply plugin: "io.spring.dependency-management"
apply plugin: 'docker'


group = 'com.leilei'
version = '1.0.0'
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
archivesBaseName = 'dev-ops-gradle-test'

repositories {
	mavenLocal()
	maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
	maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' }
	maven { url 'https://jitpack.io' }
	maven { url 'https://repo1.maven.org/maven2/' }
	mavenCentral()
}

docker {
	baseImage 'adoptopenjdk/openjdk8-openj9'
	maintainer 'lei'
}

task buildDocker(type: Docker, dependsOn: build) {
	addFile("${archivesBaseName}-${version.toString()}.jar", "app.jar")
	entryPoint(["sh", "-c", 'java  $JAVA_OPTIONS -jar  app.jar $APP_OPTIONS'])
	doFirst {
		copy {
			from jar
			into stageDir
		}
	}
}

ext {
	set('springBootVersion', "2.3.12.RELEASE")
	set('springCloudVersion', "Hoxton.SR12")
	set('SpringCloudAlibabaVersion', "2.2.7.RELEASE")
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
}


dependencyManagement {
	imports {
		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
		mavenBom "com.alibaba.cloud:spring-cloud-alibaba-dependencies:${SpringCloudAlibabaVersion}"
	}
}


configurations {
	all*.exclude module: 'spring-boot-starter-logging'
	all*.exclude module: 'logback-classic'
	all*.exclude module: 'log4j-over-slf4j'
	all*.exclude module: 'slf4j-simple'

}

tasks.named('test') {
	useJUnitPlatform()
}

MAVEN项目

dockerfile文件

设置与pom.xml在同一目录位置下

image-20221017162106250

dockerfile文件内容

# 父镜像
FROM adoptopenjdk/openjdk8-openj9

# 作者
MAINTAINER leilei

# jar拷贝
ADD *.jar app.jar

# 执行命令
ENTRYPOINT ["sh","-c","java $JAVA_OPTIONS -jar app.jar $APP_OPTIONS"]

pom.xml配置打包插件

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>1.0.0</version>
                <configuration>
                    <!-- 指定初步构建后的镜像名-->
                    <imageName>${project.groupId}/${project.name}:${project.version}</imageName>
                    <!-- 指定 Dockerfile 路径-->
                    <dockerDirectory>${basedir}</dockerDirectory>
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>
        </plugins>
    </build>

三、Jenkins打包

欲打包项目配置

1、创建TAG

image-20221016164423848

jenkins配置

1、创建任务

image-20221016162915754

2、选择参数化构建

2.1、选择JDK参数,指定 jdk版本

image-20221016163026469

2.2、选择字符参数,设置版本号

image-20221016163047450

2.3、选择字符参数,设置分支

image-20221016163127971

3、设置GIT项目

3.1、地址设置

我这里选择的是gitee,在公司开发里,一会公司会自己搭建Gitlab

image-20221016163201736

3.2、设置对应源码地址账户密码认证

例如我上边是gitee,则我需要配置Gitee的账户密码,注意该账户密码需要能够拉取到你设置的项目仓库的权限

image-20221016163309708

3.3、确定拉取方式

这里配置了需要对应项目提前构建好对应的tag,我们jenkins打包任务会进行拉取

refs/tags/${version}-${branch}s

image-20221016164222076

个人比较推荐Tag的方式,这样有一个版本迭代的过程,不但方便管理查看,而且在遇到问题时根据镜像回滚也非常方便的,后续使用了rancher,会有更多丝滑的操作 灰度发布、扩缩策略等。

image-20221016164322409

4、构建日志设置

image-20221016163433132

5、构建脚本设置

5.1、项目编译脚本
5.1.1、MAVEN项目

image-20221017162521766

5.1.2、Gradle项目

选中编译脚本

image-20221016163826845

image-20221016163912132

5.2、 jenkins打包推送脚本
5.2.1、 脚本一:打包>>推送远程仓库

这种方式更适用于rancher编排,jenkins只需要负责将镜像打至远程仓库,rancher负责镜像拉取与主机负载均衡等操作

#!/bin/bash
set +v

echo 版本号:${version}
echo 分支:${branch}
echo 代码标签:refs/tags/${version}-${branch}

# -------------------项目配置-------------------

# 项目名称
PROJECT_NAME=你的项目名

# 项目包路径
PROJECT_PACKAGE=你的项目包路径

# 项目版本
PROJECT_VERSION=${version}

# 项目分支
PROJECT_BRANCH=${branch}

# -------------------编译配置-------------------

# 远端仓库地址
MIRROR_WAREHOUSE=你的远端仓库地址

# 远端仓库组织(命名空间)
MIRROR_WAREHOUSE_ORG=你的命令空间

# 远端仓库用户
MIRROR_WAREHOUSE_USER=登陆账户

# 远端仓库密钥,注意这里并不是登陆账户密码,而是设置的镜像仓库密钥
MIRROR_WAREHOUSE_PWD=密钥

# 编译后镜像名,项目包路径/项目名称:项目版本
JENKINS_IMAGE_NAME=${PROJECT_PACKAGE}/${PROJECT_NAME}:${PROJECT_VERSION}

# 远端仓库镜像名,远端仓库地址/远端仓库组织/项目名称:项目版本-项目分支
WAREHOUSE_IMAGE_NAME=${MIRROR_WAREHOUSE}/${MIRROR_WAREHOUSE_ORG}/${PROJECT_NAME}:${PROJECT_VERSION}-${PROJECT_BRANCH}

# -------------------运行配置-------------------

# 将镜像标记为远程仓库名
docker tag ${JENKINS_IMAGE_NAME} ${WAREHOUSE_IMAGE_NAME}

# 登录远程仓库
docker login --username=${MIRROR_WAREHOUSE_USER} --password=${MIRROR_WAREHOUSE_PWD} ${MIRROR_WAREHOUSE}

# 推送镜像至远程仓库
docker push ${WAREHOUSE_IMAGE_NAME}
5.2.2 、脚本二:打包>>推送远程仓库>>对应服务器启动

有时候我们在开发环境也需要打包,但希望构建完成后直接推送到对应测试服务器地址并启动,这种方式适合portainer部署,更适合于小型项目或开发部署,无法动态添减节点与负载

5.2.2.1、前置条件:目标服务器docker需开启远程访问
# 修改如下配置
vim /usr/lib/systemd/system/docker.service

# 修改ExecStart信息
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock

# 重启docker
systemctl daemon-reload
systemctl restart docker

image-20221016221406485

5.2.2.2、脚本

注意根据自己项目进行调整

#!/bin/bash
set +v

echo 版本号:${version}
echo 分支:${branch}
echo 代码标签:refs/tags/${version}-${branch}

# -------------------主机配置-------------------

# 步骤配置:1 推送至远程仓库;2 从远程仓库拉取镜像运行;3 推送至远程仓库,并拉取镜像运行
STEP=3
# -------------------项目配置-------------------

# 项目名称
PROJECT_NAME=你的项目名

# 项目包路径
PROJECT_PACKAGE=你的项目包路径

# 项目版本
PROJECT_VERSION=${version}

# 项目分支
PROJECT_BRANCH=${branch}

# 项目端口
PROJECT_PORT=项目端口

# 项目参数 比如指定微服务相关配置  --spring.cloud.config.label=${PROJECT_BRANCH},按需添加
PROJECT_APP_OPTIONS="--spring.cloud.config.label=${PROJECT_BRANCH} --eureka.instance.ipAddress=${HOST_IP}"

# 项目日志目录
PROJECT_LOG_PATH=/${PROJECT_NAME}/logs/

# 主机IP,多个IP以空格隔开,如:(192.168.63.1 192.168.63.2)
HOST_IP=(主机IP)


# 主机端口,多个端口以空格隔开,如:(8090 8090),注意数量需要和<主机IP>保持一致
HOST_PORT=(项目需要映射的宿主机端口)

# 主机日志目录
HOST_LOG_PATH=/${PROJECT_NAME}/logs/

# -------------------编译配置-------------------

# 远端仓库地址
MIRROR_WAREHOUSE=你的远端仓库地址

# 远端仓库组织(命名空间)
MIRROR_WAREHOUSE_ORG=你的命令空间

# 远端仓库用户
MIRROR_WAREHOUSE_USER=登陆账户

# 远端仓库密钥,注意这里并不是登陆账户密码,而是设置的镜像仓库密钥
MIRROR_WAREHOUSE_PWD=密钥

# 编译后镜像名,项目包路径/项目名称:项目版本
JENKINS_IMAGE_NAME=${PROJECT_PACKAGE}/${PROJECT_NAME}:${PROJECT_VERSION}

# 远端仓库镜像名,远端仓库地址/远端仓库组织/项目名称:项目版本-项目分支
WAREHOUSE_IMAGE_NAME=${MIRROR_WAREHOUSE}/${MIRROR_WAREHOUSE_ORG}/${PROJECT_NAME}:${PROJECT_VERSION}-${PROJECT_BRANCH}

# -------------------环境配置-------------------

# 语言环境配置,快速启动;编码设置;(可自定义增加其他参数,如限制内存使用:-Xms128m -Xmx 512m)
JAVA_OPTIONS="-Duser.timezone=GMT+8 -Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF-8"

# 容器环境配置,日志限制;时区同步;日志挂载;其他挂载
DOCKER_ENVIRONMENT="--log-opt max-size=1m --log-opt max-file=1 -v /etc/localtime:/etc/localtime:ro -v ${HOST_LOG_PATH}:${PROJECT_LOG_PATH}  -d"

# DOCKER远程端口
DOCKER_REMOTE_PORT=2375

# -------------------运行配置-------------------

# 1 推送至远程仓库
function step1(){
	
	# 将镜像标记为远程仓库名
	docker tag ${JENKINS_IMAGE_NAME} ${WAREHOUSE_IMAGE_NAME}
	
	# 删除历史编译镜像,释放空间
	if [ -n "$(docker images | grep none | awk '{print $3}')" ]; then
		docker images | grep none | awk '{print $3}' | sort -u | xargs docker rmi -f
	fi
	
	# 登录远程仓库
	docker login -u ${MIRROR_WAREHOUSE_USER} -p ${MIRROR_WAREHOUSE_PWD} ${MIRROR_WAREHOUSE}
	
	# 推送镜像至远程仓库
	docker push ${WAREHOUSE_IMAGE_NAME}
	
	# 删除本次编译镜像,释放空间
	if [ -n "$(docker images | grep ${PROJECT_NAME} | awk '{print $3}')" ]; then
		docker images | grep ${PROJECT_NAME} | awk '{print $3}' | sort -u | xargs docker rmi -f
	fi
}

# 2 从远程仓库拉取镜像运行
function step2(){
	
	# 主机与端口配置校验
	if [ ${#HOST_IP[@]} -eq ${#HOST_PORT[@]} ];then
		
		# 遍历主机列表
		for ip_index in "${!HOST_IP[@]}";
		do
			remote_ip=${HOST_IP[$ip_index]}
			remote_port=${HOST_PORT[$ip_index]}
			
			echo "------------远程主机:$remote_ip:$remote_port 拉取远程仓库镜像------------"
			docker login -u ${MIRROR_WAREHOUSE_USER} -p ${MIRROR_WAREHOUSE_PWD} ${MIRROR_WAREHOUSE}
			docker -H $remote_ip:${DOCKER_REMOTE_PORT} pull ${WAREHOUSE_IMAGE_NAME}
			
			if [ -n "$(docker -H $remote_ip:${DOCKER_REMOTE_PORT} ps -a | grep ${PROJECT_NAME}.$remote_port | awk '{print $1}' | sed 's/%//g')" ]; then
				echo "------------远程主机:$remote_ip:$remote_port 停止并删除容器------------"
				docker -H $remote_ip:${DOCKER_REMOTE_PORT} stop $(docker -H $remote_ip:${DOCKER_REMOTE_PORT} ps -a | grep ${PROJECT_NAME}.$remote_port | awk '{print $1}' | sed 's/%//g')
				docker -H $remote_ip:${DOCKER_REMOTE_PORT} rm -f $(docker -H $remote_ip:${DOCKER_REMOTE_PORT} ps -a | grep ${PROJECT_NAME}.$remote_port | awk '{print $1}' | sed 's/%//g')
			fi

			echo "------------远程主机:$remote_ip:$remote_port 启动容器------------"
			docker -H $remote_ip:${DOCKER_REMOTE_PORT} run -e JAVA_OPTIONS="${JAVA_OPTIONS}" -e APP_OPTIONS="${PROJECT_APP_OPTIONS} --eureka.instance.ip-address=$remote_ip" ${DOCKER_ENVIRONMENT} --name ${PROJECT_NAME}.$remote_port -p $remote_port:${PROJECT_PORT} ${WAREHOUSE_IMAGE_NAME}
			
			# 删除历史编译镜像,释放空间
			#if [ -n "$(docker -H $remote_ip:${DOCKER_REMOTE_PORT} images | grep none | awk '{print $3}')" ]; then
			#	docker -H $remote_ip:${DOCKER_REMOTE_PORT} images | grep none | awk '{print $3}' | sort -u | xargs docker -H $remote_ip:${DOCKER_REMOTE_PORT} rmi -f
			#fi
		done
	else
		echo "HOST_IP HOST_PORT 数量不匹配,请重新配置"
	fi
}

# 3 推送至远程仓库,并拉取镜像运行
function step3(){
	step1
	step2
}

# 步骤控制
if [ ${STEP} -eq 1 ];then
	step1
elif [ ${STEP} -eq 2 ];then
	step2
else
	step3
fi

远程仓库管理

我这里远程仓库使用的是阿里云,需要在阿里云上开通容器镜像服务

1、开启容器镜像服务

因为,我这里是演示,故此只有使用个人版

image-20221016164645377

2、设置命名空间

命名空间的实际作用呢,可以理解为分组,比如公司里 A小组一个命令空间 B小组一个命令空间

image-20221016164738693

3、查看推送打包命令示例

可能有小帅哥比较好奇,唉,你咋知道Shell该这么写呢?我们要学会使用官网以及官网文档,在我不清楚镜像仓库到底是什么的时候,我点击了一下创建,在创建完后即理解了这个真正的含义,又拿到了相应命令

image-20221016165134630

注意点:此镜像仓库并不是传统意义上的dockerHub那种包罗万象拥有N多镜像与版本,它仅仅只是针对一个镜像的管理,里边有该镜像的种种迭代版本,你可以理解为某具体镜像以及其镜像迭代记录

image-20221016165528867

点击我们创建好的镜像库,里边有详细的命令介绍,于是我根据此命令,改成了对应的Shell

image-20221016165734448

4、镜像访问凭证设置

我需要设置好一个固定的访问凭证,并在Shell脚本中写明,这样才能将对应项目打成的镜像推送到远程仓库中

image-20221016165902260

执行打包

方式一:打包>>推送远程仓库

1、打包

在经过一系列的失败后,流程终于完全跑通

image-20221016170107574

image-20221016170218877

image-20221016170235263

2、阿里云仓库查看对应镜像

image-20221016170614595

image-20221016170527725

加更maven打包

image-20221017162729027

方式二:打包>>推送远程仓库>>对应服务器启动

1、打包

image-20221016221807926

2、对应服务器查看镜像与容器启动情况

image-20221016222210772

加更maven打包

image-20221017164059064

image-20221017164202852

remark 202210162225,后续加更Maven项目打包

remark 202210171626,已加更Maven项目打包

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值