一、集成工具下载
JDK
最新版jdk内置版本为11,如需要兼容jdk8请参考我上一篇文章
jdk11版本jenkins打包jdk8项目,同时兼容jdk11与jdk8
编译工具
gradle
maven
二、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在同一目录位置下
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
jenkins配置
1、创建任务
2、选择参数化构建
2.1、选择JDK参数,指定 jdk版本
2.2、选择字符参数,设置版本号
2.3、选择字符参数,设置分支
3、设置GIT项目
3.1、地址设置
我这里选择的是gitee,在公司开发里,一会公司会自己搭建Gitlab
3.2、设置对应源码地址账户密码认证
例如我上边是gitee,则我需要配置Gitee的账户密码,注意该账户密码需要能够拉取到你设置的项目仓库的权限
3.3、确定拉取方式
这里配置了需要对应项目提前构建好对应的tag,我们jenkins打包任务会进行拉取
refs/tags/${version}-${branch}s
个人比较推荐Tag的方式,这样有一个版本迭代的过程,不但方便管理查看,而且在遇到问题时根据镜像回滚也非常方便的,后续使用了rancher,会有更多丝滑的操作 灰度发布、扩缩策略等。
4、构建日志设置
5、构建脚本设置
5.1、项目编译脚本
5.1.1、MAVEN项目
5.1.2、Gradle项目
选中编译脚本
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
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、开启容器镜像服务
因为,我这里是演示,故此只有使用个人版
2、设置命名空间
命名空间的实际作用呢,可以理解为分组,比如公司里 A小组一个命令空间 B小组一个命令空间
3、查看推送打包命令示例
可能有小帅哥比较好奇,唉,你咋知道Shell该这么写呢?我们要学会使用官网以及官网文档,在我不清楚镜像仓库到底是什么的时候,我点击了一下创建,在创建完后即理解了这个真正的含义,又拿到了相应命令
注意点:此镜像仓库并不是传统意义上的dockerHub那种包罗万象拥有N多镜像与版本,它仅仅只是针对一个镜像的管理,里边有该镜像的种种迭代版本,你可以理解为某具体镜像以及其镜像迭代记录
点击我们创建好的镜像库,里边有详细的命令介绍,于是我根据此命令,改成了对应的Shell
4、镜像访问凭证设置
我需要设置好一个固定的访问凭证,并在Shell脚本中写明,这样才能将对应项目打成的镜像推送到远程仓库中
执行打包
方式一:打包>>推送远程仓库
1、打包
在经过一系列的失败后,流程终于完全跑通
2、阿里云仓库查看对应镜像
加更maven打包
方式二:打包>>推送远程仓库>>对应服务器启动
1、打包
2、对应服务器查看镜像与容器启动情况
–
加更maven打包
–
remark 202210162225,后续加更Maven项目打包
remark 202210171626,已加更Maven项目打包