目录
添加Send build artifacts over SSH
添加的job是基于git、maven和docker私有仓库,实现自动构建jar包、生成docker镜像,并能够自动docker容器的过程。还可以根据选择的参数,实现检出git不同分支,生成不同版本的docker镜像,并发布到开发服务器或者测试服务器。我这边就拿一个多模块的基于maven构建的项目来说明
-
添加ssh server
在系统管理->系统配置->Publish over SSH, 添加一个ssh server ,需要注意的是Remote Directory要注意设置,建议设置为/, 不然通过ssh发送文件会不行,笔者就曾经漏掉这个,排查了半天
新建JOB
注意是勾选构建一个maven项目
General一般
参数化构建过程
添加branch参数
作用:branche参数用来选择构建的代码分支是dev还是test
选择添加Active Choices Parameter
勾选groovy script
groovy脚本
return[
"dev","test"
]
version参数
作用:version参数来控制docker镜像版本是latest还是1.0。
添加Active Choices Reactive Parameter,能够根据别的参数改变自己的值
version参数会根据branch参数变化值 ,注意在 Referenced parameters项填入branch
groovy脚本
dev=["latest"]
test=["1.0"]
if (branch.equals("dev")) {
return dev
} else if (branch.equals("test")) {
return test
} else {
return ["latest"]
}
env参数
作用:env参数把程序发布到哪台主机
添加Extended Choice Parameter类型参数,参数类型是Radio Buttions
choose source for value和chose source for value description分别写入dev,test和开发环境,测试环境。注意多个选项之前用逗号隔开,是delimter指定的
Source Code Management源代码
要把构建的源代码放在这边设置,选择
Multiple SCMs,再选择git来检出,因为这个项目有依赖多个子项目,这个选项可以设置多个git源代码
注意在Branch Specifier (blank for 'any')中写入*/${branch}, 这是之前设置的branch参数
注意设置检出项目的子目录,点击 Additional Behaviours -> Check out to a sub-directory,再在 Local subdirectory for repo 写入要检出代码存放的目录
Pre Steps
这边就是构建上面检出的主项目所依赖的其他项目的源代码
脚本如下
java -version
sudo sed -i '$d' /etc/hosts
echo $env
if [ "$env" == "test" ]
then
echo 'test'
sudo sed -i '$a192.168.133.X imageserver' /etc/hosts
else
echo "++++dev++++"
sudo sed -i '$a192.168.133.X imageserver' /etc/hosts
fi
docker login imageserver:8082 -u用户名 -p密码
cd /var/lib/jenkins2/workspace/iotbd/nledu-iotbd-common
mvn clean install -Dmaven.test.skip=true
cd /var/lib/jenkins2/workspace/iotbd/nledu-iotbd-system
mvn clean package install -pl nledu-iotbd-system-fegin -am -Dmaven.test.skip=true
cd /var/lib/jenkins2/workspace/iotbd/nledu-iotbd-ci
mvn clean package install -pl nledu-iotbd-ci-fegin -am -Dmaven.test.skip=true
mvn clean package install -pl nledu-iotbd-ci-stream -am -Dmaven.test.skip=true
cd /var/lib/jenkins2/workspace/iotbd/nledu-iotbd-vm
mvn clean package install -pl nledu-iotbd-vm-fegin -am -Dmaven.test.skip=true
cd /var/lib/jenkins2/workspace/iotbd/nledu-iotbd-websocket
mvn clean package install -pl nledu-iotdb-websocket-feign -am -Dmaven.test.skip=true
cd /var/lib/jenkins2/workspace/iotbd/nledu-iotbd-vm
mvn clean package install -pl nledu-iotbd-vm-fegin -am -Dmaven.test.skip=true
说一下下面脚本的作用
sudo sed -i '$d' /etc/hosts
就是/etc/hosts删除最后一行
sudo sed -i '$a192.168.133.X imageserver' /etc/hosts
就是往/etc/hosts文件最后一行添加192.168.133.93 imageserver
上面的脚本,其实就是切换不同的docker仓库,因为开发服务器和测试服务器的docker 仓库地址不同,通过修改hosts文件来切换
Build构建
总体
root pom就是主项目的pom文件路径
golas and options脚本就是构建主项目,如下
clean package docker:build -DpushImageTag -Dmaven.test.skip=true -Ddocker.image.version=${version}
${version}是version参数传进去的值
自定义工作空间
点击高级,设置自己的工作空间,工作空间的设置对于Send build artifacts over SSH非常重要,Send build artifacts over SSH的source files的地址就是基于这个工作的相对目录,所以最好要设置。
选择Use custom workspace,在Directory写入工作空间目录
重要配置文件
主项目的源代码目录的docker目录下有4个跟构建相关的脚本,以及docker-compose.yaml要用到的参数脚本dev.env,都给粘出来,供参考
pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>nledu-iotbd-ci</artifactId>
<groupId>com.newland.iotbd.ci</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.newland.iotbd.ci.core</groupId>
<artifactId>nledu-iotbd-ci-core</artifactId>
<properties>
<docker.image.prefix>imageserver:8082/iotbd</docker.image.prefix>
<docker.image.version>${project.version}</docker.image.version>
<itext.version>7.1.12</itext.version>
</properties>
<dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.newland.iotbd.ci.core.NleduIotbdCICoreApplication</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
<manifestEntries>
<Class-Path>.</Class-Path>
<Timestamp>${maven.build.timestamp}</Timestamp>
</manifestEntries>
</archive>
<!-- <excludes>
<exclude>**/*.properties</exclude>
<exclude>**/*.xml</exclude>
</excludes>-->
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<finalName>${project.artifactId}</finalName>
<descriptors>
<descriptor>src/main/resources/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.2</version>
<configuration>
<imageName>${docker.image.prefix}/${project.artifactId}:${docker.image.version}</imageName>
<dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
<!-- <dockerHost>http://imageserver:2375</dockerHost>-->
<!--强制覆盖 镜像-->
<forceTags>true</forceTags>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<!-- <include>${project.build.finalName}-all.tar.gz</include>-->
</resource>
</resources>
<imageTags>
<imageTag>${docker.image.version}</imageTag>
</imageTags>
<!-- push -->
<serverId>docker-registry</serverId>
<registryUrl>http://${docker.image.prefix}</registryUrl>
</configuration>
</plugin>
</plugins>
</build>
</project>
Dockerfile
# FROM imageserver:6000/java:8
#FROM imageserver:8082/iotbd/centos8-jdk11.0.7:2020.08.10
FROM imageserver:8082/iotbd/centos8-jdk11.0.7:20200901
MAINTAINER yuxs "yuxs@newlandcomputer.com"
RUN mkdir -p /app
WORKDIR /app
ADD nledu-iotbd-ci-core-all.tar.gz .
COPY docker-start.sh ./nledu-iotbd-ci-core/
RUN mkdir -p log
ENV TZ Asia/Shanghai
EXPOSE 8806
ENTRYPOINT ["/bin/bash","/app/nledu-iotbd-ci-core/docker-start.sh"]
docker-start.sh
用来容器里头启动java服务
#!/bin/bash
APP_ENV=${appenv:-dev}
APP_NAME=${appname}
APP_VERSION=${appversion:-1.0-SNAPSHOT}
LOG_MAX_SIZE=${log_max_size:-20MB}
# change directory to program dir
FWDIR="$(cd `dirname $0`; pwd)"
cd ${FWDIR}
if [ ! -d ${FWDIR}/java.pid ]; then
touch ${FWDIR}/java.pid
fi
OSUSER=$(id -nu)
PSNUM=$(cat ${FWDIR}/java.pid)
if [[ "$PSNUM" -ne "" ]]; then
echo ${APP_NAME}" has been started! stop first."
exit;
fi
echo "Running in docker!"
#-XX:+UseCGroupMemoryLimitForHeap \
#-XX:+UnlockExperimentalVMOptions \
#-XX:MaxRAMFraction=1 \
if [ $skywalking -eq 1 ]; then
java -DSW_AGENT_NAME=${APP_NAME} \
-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=${skywalking_url}:${skywalking_port} \
-DSW_LOGGING_LEVEL=debug \
-javaagent:\/app\/skywalking\/agent\/skywalking-agent.jar \
-XX:+UnlockExperimentalVMOptions \
-XX:MaxRAMPercentage=90.0 \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/app/${APP_NAME}/log/ \
-Dspring.profiles.active=${APP_ENV} \
-Dapp.name=${APP_NAME} \
-Dapp.env=${APP_ENV} \
-Dmax.size=${LOG_MAX_SIZE} \
-Duser.dir=${FWDIR} \
-jar ${APP_NAME}-${APP_VERSION}.jar
else
java -XX:+UnlockExperimentalVMOptions \
-XX:MaxRAMPercentage=90.0 \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/app/${APP_NAME}/log/ \
-Dspring.profiles.active=${APP_ENV} \
-Dapp.name=${APP_NAME} \
-Dapp.env=${APP_ENV} \
-Dmax.size=${LOG_MAX_SIZE} \
-Duser.dir=${FWDIR} -jar ${APP_NAME}-${APP_VERSION}.jar
fi
#java -XX:+UnlockExperimentalVMOptions \
# -XX:MaxRAMPercentage=90.0 \
# -XX:+HeapDumpOnOutOfMemoryError \
# -XX:HeapDumpPath=/app/${APP_NAME}/log/ \
# -Dspring.profiles.active=${APP_ENV} \
# -Dapp.name=${APP_NAME} \
# -Dapp.env=${APP_ENV} \
# -Dmax.size=${LOG_MAX_SIZE} \
# -javaagent:/home/agent/skywalking-agent.jar \
# -Dskywalking.agent.service_name=${APP_NAME} \
# -Dskywalking.collector.backend_service=${skywalking_url}:${skywalking_port} \
# -Duser.dir=${FWDIR} -jar ${APP_NAME}-${APP_VERSION}.jar
# #-XshowSettings:vm -version \
# #-XX:+PrintFlagsFinal -version | grep -Ei "maxheapsize|maxram"
docker-compose.yaml
version: '3'
services:
app-name:
container_name: app-name
image: imageserver:8082/iotbd/app-name:image-version
restart: on-failure
privileged: true
environment:
appenv: app-env
appname: app-name
appversion: 1.0-SNAPSHOT
env_file:
- /home/deploy_script/app-env.env
ports:
- 8806:8806
- 9991:9991
volumes:
- /home/log/app-name:/app/app-name/log
deploy:
resources:
limits:
memory: 2G
network_mode: "host"
注意container_name、image、environment这几项的值最后会被Post Steps步骤脚本替换。这所以这么设计,是因为脚本可以复用,项目的具体名称可以通过sed命令来替换,替换过的docker-compose.yaml如下,注意观察
version: '3'
services:
nledu-iotbd-ci-core:
container_name: nledu-iotbd-ci-core
image: imageserver:8082/iotbd/nledu-iotbd-ci-core:latest
restart: on-failure
privileged: true
environment:
appenv: dev
appname: nledu-iotbd-ci-core
appversion: 1.0-SNAPSHOT
env_file:
- /home/deploy_script/dev.env
ports:
- 8806:8806
- 9991:9991
volumes:
- /home/log/nledu-iotbd-ci-core:/app/nledu-iotbd-ci-core/log
deploy:
resources:
limits:
memory: 2G
network_mode: "host"
jenkins-deployment.sh
用来启动docker
#!/bin/bash
export version=xxxVersion
export app_name=xxxapp_name
export app_env=xxxapp_env
sed -i "s/app-name/$app_name/g" ./docker-compose.yaml
sed -i "s/image-version/$version/g" ./docker-compose.yaml
sed -i "s/app-env/$app_env/g" ./docker-compose.yaml
re=`docker images -f "dangling=true" -q`
if [ -n "$re" ];then
docker rmi -f `docker images -f "dangling=true" -q`
else
echo ''
fi
docker-compose --compatibility down
re1=`docker images imageserver:8082/iotbd/$app_name:$version -q`
if [ -n "$re1" ];then
docker rmi imageserver:8082/iotbd/$app_name:$version
else
echo ''
fi
docker-compose --compatibility up -d
# 打印日志很好用
docker-compose --compatibility logs -f $app_name &
#kubectl create -f deployment-$app_name.yaml
dev.env文件
这个是环境变量文件,是docker-compose.yaml指定的环境变量文件
# 注册服务器
nledu-iotbd-discovery1=192.168.133.X
nledu-iotbd-discovery1-port=8765
app.discovery.enabled=true
Post Steps
这步是构建镜像后的辅助工作,如删除dangling镜像,替换jenkins-deployment.sh的一些值
脚本
cd /var/lib/jenkins2/workspace/iotbd/nledu-iotbd-ci/nledu-iotbd-ci-core
#ls
#docker save -o ./target/nledu-etmlab-hc-education:$version.tar imageserver:8082/nledu-etmlab-hc-education:$version
sed -i 's/xxxVersion/'$version'/g' ./src/main/docker/jenkins-deployment.sh
sed -i 's/xxxapp_name/nledu-iotbd-ci-core/g' ./src/main/docker/jenkins-deployment.sh
sed -i 's/xxxapp_env/'$env'/g' ./src/main/docker/jenkins-deployment.sh
re=`docker images -f "dangling=true" -q`
if [ -n "$re" ];then
docker rmi -f `docker images -f "dangling=true" -q`
else
echo ''
fi
Post-build Actions
添加Send build artifacts over SSH
SSH Server
#!bin/sh
mkdir -p /home/deploy_script2/nledu-iotbd-ci/nledu-iotbd-ci-core/
cd /home/deploy_script2/nledu-iotbd-ci/nledu-iotbd-ci-core/
ls
echo "============upload over=============="
chmod +x jenkins-deployment.sh
docker login imageserver:8082 -u用户名 -p密码
./jenkins-deployment.sh
while true
do
re1=`curl http://127.0.0.1:8806/actuator/health`
if [ $? -eq 0 ];then
echo "+++++++++++"$re1
break
fi
sleep 2
done
这里头会自动检测服务是否正常启动的脚本,注意观察
点击高级
勾选exec in pty ,不然执行脚本的时候不会自动退出
根据参数自动选择哪个ssh server
由于我这边添加了开发服务器和测试服务器,构建的时候,选择可以选择哪个环境来部署,就是通过env参数来控制的。
设置label
Name下的高级
label填入dev或者test,dev表示开发服务器,test表示测试服务器
Parameterized publishing
这个用来设置哪个参数来控制要发布的服务器, 这边是env参数。点Send build artifacts over SSH下的高级,如图所示
设置参数env
总结
最后选择保存就行了。
效果如图所示,选择branch为dev ,version变成latest,branch选择test,version变成1.0。env勾选开发环境就是部署到开发服务器,选择测试环境就是部署到测试服务器
测试