Generally speaking, a project deployment consists of: pull code->build->test->package->deploy and other processes. If we often need to deploy projects, especially in the era of microservices, when there are a lot of services, Continuous testing, packaging and deployment, it is estimated that someone has to do this all day long, and this is tedious and repetitive, meaningless, so a set of automated builds capable of continuous integration, continuous delivery, and continuous deployment is needed process.
Jenkins is a leader in open source CI&CD software, providing more than 1,000 plug-ins to support construction, deployment, automation, and meet the needs of any project. We can use Jenkins to build and deploy our projects, for example, get the code from our code repository, then package our code into an executable file, and then execute the script through the remote ssh tool to run our project
1. Preparation
In a real production environment, there may be multiple servers, but I use it for practice, and there is no extra server at hand, only one. So I deployed both Jenkins and my Spring Boot project to one server.
Since Docker is used to install Jenkins this time, the three necessary environment configurations of JDK, Maven, and Docker need to be installed in advance on the server. I won’t go into too much detail about the installation of these three environments here, you can check the information and install it yourself
1. Check the JDK environment
java -version
[root@liulihui home]# java -version
java version "1.8.0_231"
Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)
[root@liulihui home]#
2. Check the Maven environment
[root@liulihui home]# mvn -v
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: /usr/local/maven/apache-maven-3.6.3
Java version: 1.8.0_231, vendor: Oracle Corporation, runtime: /usr/local/java/jdk/jdk1.8.0_231/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "3.10.0-1160.80.1.el7.x86_64", arch: "amd64", family: "unix"
[root@liulihui home]#
3. Check the Docker environment
[root@liulihui home]# docker version
Client: Docker Engine - Community
Version: 20.10.21
API version: 1.41
Go version: go1.18.7
Git commit: baeda1f
Built: Tue Oct 25 18:04:24 2022
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.21
API version: 1.41 (minimum version 1.12)
Go version: go1.18.7
Git commit: 3056208
Built: Tue Oct 25 18:02:38 2022
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.12
GitCommit: a05d175400b1145e5e6a735a6710579d181e7fb0
runc:
Version: 1.1.4
GitCommit: v1.1.4-0-g5fd4c4d
docker-init:
Version: 0.19.0
GitCommit: de40ad0
[root@liulihui home]#
2. Installation and configuration of Jenkins
1. Docker search jenkins image
[root@liulihui home]# docker search jenkins
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
jenkins DEPRECATED; use "jenkins/jenkins:lts" instead 5585 [OK]
jenkins/jenkins The leading open source automation server 3330
jenkins/jnlp-slave a Jenkins agent which can connect to Jenkins… 153 [OK]
jenkins/inbound-agent 81
bitnami/jenkins Bitnami Docker Image for Jenkins 58 [OK]
jenkins/agent 49
jenkins/slave base image for a Jenkins Agent, which includ… 48 [OK]
jenkins/ssh-slave A Jenkins slave using SSH to establish conne… 38 [OK]
jenkins/ssh-agent Docker image for Jenkins agents connected ov… 28
jenkins/jnlp-agent-docker 8
jenkins/jnlp-agent-maven A JNLP-based agent with Maven 3 built in 7
jenkins/pct Plugin Compat Tester 5 [OK]
jenkins/evergreen An automatically self-updating Jenkins distr… 5
jenkins/jnlp-agent-python A JNLP-based agent with Python built in 3
jenkins/jenkins-experimental Experimental images of Jenkins. These images… 3 [OK]
jenkins/jnlp-agent-alpine 2
jenkins/jnlp-agent-coresdk 2
rancher/jenkins-jenkins 1
jenkins/jnlp-agent-node 1
jenkins/jenkinsfile-runner Jenkinsfile Runner packages 1
jenkins/core-pr-tester Docker image for testing pull-requests sent … 1
jenkins/ath Jenkins Acceptance Test Harness 1 [OK]
jenkins/jnlp-agent-ruby 1
rancher/jenkins-slave Jenkins Build Slave 0 [OK]
rancher/jenkins-jnlp-slave
2. Docker downloads the jenkins image
[root@liulihui home]# docker pull jenkins/jenkins:lts
lts: Pulling from jenkins/jenkins
647acf3d48c2: Pull complete
832e288237bc: Pull complete
ea194d1bd1da: Pull complete
98569593b9fd: Pull complete
dfe249e8cdf2: Pull complete
0f6f2e6d37bb: Pull complete
07fcb98649b6: Pull complete
1e33c26b1882: Pull complete
7b24f0e29fe1: Pull complete
4d90ef3a8f3b: Pull complete
d98c8e675bea: Pull complete
b45fc2bf9fd7: Pull complete
d6e1fda9effc: Pull complete
3635a44047f2: Pull complete
486e1776d3bc: Pull complete
41233d151800: Pull complete
14a67803c2b3: Pull complete
Digest: sha256:c1d02293a08ba69483992f541935f7639fb10c6c322785bdabaf7fa94cd5e732
Status: Downloaded newer image for jenkins/jenkins:lts
docker.io/jenkins/jenkins:lts
# 查看镜像
[root@liulihui home]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jenkins/jenkins lts 2a4bbe50c40b 13 months ago 441MB
java 8 d23bdf5b1b1b 5 years ago 643MB
[root@liulihui home]#
3. Run Jenkins in a Docker container
# 命令如下:
docker run -p 9080:8080 --name liulihui-jenkins \
-u root \
-v /mydata/jenkins_home:/var/jenkins_home \
-v /usr/local/java/jdk/jdk1.8.0_231:/usr/local/jdk1.8 \
-v /usr/local/maven/apache-maven-3.6.3:/usr/local/apache-maven-3.6.3 \
-v $(which docker):/usr/bin/docker \
-v /var/run/docker.sock:/var/run/docker.sock \
-d jenkins/jenkins:lts
# 参数说明:
-p 9080:8080 端口映射(将容器的8080端口【后面的8080】映射到服务器的9080端口【前面的9080】,云服务器需要开通9080端口供外网访问)
--name 容器名字
-u root 用户名
-v /mydata/jenkins_home:/var/jenkins_home 将配置文件夹挂在到主机(:前面的是主机目录,后面的是容器目录)
-v /usr/local/java/jdk/jdk1.8.0_231:/usr/local/jdk1.8 是把linux下的jdk和容器内的关联(配置Jenkins时使用,:前面的是主机目录,后面的是容器目录)
-v /usr/local/maven/apache-maven-3.6.3:/usr/local/apache-maven-3.6.3 是把linux下的maven和容器内的关联(配置Jenkins时使用,:前面的是主机目录,后面的是容器目录)
-v $(which docker):/usr/bin/docker 是可以在Jenkins容器里使用我们Linux下的docker
-v /var/run/docker.sock:/var/run/docker.sock 是可以在Jenkins容器里使用我们Linux下的docker
-d jenkins/jenkins:lts 后台启动 Jenkins镜像(最新版)
# 查看docker 正在运行的容器
[root@liulihui home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9363f69cc773 jenkins/jenkins:lts "/sbin/tini -- /usr/…" 19 seconds ago Up 17 seconds 50000/tcp, 0.0.0.0:9080->8080/tcp, :::9080->8080/tcp liulihui-jenkins
4. Configuration of Jenkins
After running successfully, visit this address to log in to Jenkins. For the first login, you need to enter the administrator password: http://your ip:9080/
Log in with the admin password, which can be obtained from the container startup log using the following command:
# 查看日志,获取管理员密码
[root@liulihui home]# docker logs liulihui-jenkins
Running from: /usr/share/jenkins/jenkins.war
webroot: EnvVars.masterEnvVars.get("JENKINS_HOME")
2023-01-05 06:02:04.057+0000 [id=1] INFO org.eclipse.jetty.util.log.Log#initialized: Logging initialized @707ms to org.eclipse.jetty.util.log.JavaUtilLog
2023-01-05 06:02:04.141+0000 [id=1] INFO winstone.Logger#logInternal: Beginning extraction from war file
2023-01-05 06:02:09.723+0000 [id=1] WARNING o.e.j.s.handler.ContextHandler#setContextPath: Empty contextPath
2023-01-05 06:02:09.829+0000 [id=1] INFO org.eclipse.jetty.server.Server#doStart: jetty-9.4.43.v20210629; built: 2021-06-30T11:07:22.254Z; git: 526006ecfa3af7f1a27ef3a288e2bef7ea9dd7e8; jvm 11.0.13+8
2023-01-05 06:02:10.641+0000 [id=1] INFO o.e.j.w.StandardDescriptorProcessor#visitServlet: NO JSP Support for /, did not find org.eclipse.jetty.jsp.JettyJspServlet
2023-01-05 06:02:10.757+0000 [id=1] INFO o.e.j.s.s.DefaultSessionIdManager#doStart: DefaultSessionIdManager workerName=node0
2023-01-05 06:02:10.757+0000 [id=1] INFO o.e.j.s.s.DefaultSessionIdManager#doStart: No SessionScavenger set, using defaults
2023-01-05 06:02:10.758+0000 [id=1] INFO o.e.j.server.session.HouseKeeper#startScavenging: node0 Scavenging every 660000ms
2023-01-05 06:02:11.848+0000 [id=1] INFO hudson.WebAppMain#contextInitialized: Jenkins home directory: /var/jenkins_home found at: EnvVars.masterEnvVars.get("JENKINS_HOME")
2023-01-05 06:02:12.155+0000 [id=1] INFO o.e.j.s.handler.ContextHandler#doStart: Started w.@216914{Jenkins v2.319.1,/,file:///var/jenkins_home/war/,AVAILABLE}{/var/jenkins_home/war}
2023-01-05 06:02:12.204+0000 [id=1] INFO o.e.j.server.AbstractConnector#doStart: Started ServerConnector@72cf2de5{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
2023-01-05 06:02:12.204+0000 [id=1] INFO org.eclipse.jetty.server.Server#doStart: Started @8856ms
2023-01-05 06:02:12.219+0000 [id=23] INFO winstone.Logger#logInternal: Winstone Servlet Engine running: controlPort=disabled
2023-01-05 06:02:12.576+0000 [id=30] INFO jenkins.InitReactorRunner$1#onAttained: Started initialization
2023-01-05 06:02:12.620+0000 [id=28] INFO jenkins.InitReactorRunner$1#onAttained: Listed all plugins
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.google.inject.internal.cglib.core.$ReflectUtils$2 (file:/var/jenkins_home/war/WEB-INF/lib/guice-4.0.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of com.google.inject.internal.cglib.core.$ReflectUtils$2
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
2023-01-05 06:02:14.226+0000 [id=28] INFO jenkins.InitReactorRunner$1#onAttained: Prepared all plugins
2023-01-05 06:02:14.231+0000 [id=28] INFO jenkins.InitReactorRunner$1#onAttained: Started all plugins
2023-01-05 06:02:14.249+0000 [id=28] INFO jenkins.InitReactorRunner$1#onAttained: Augmented all extensions
2023-01-05 06:02:15.935+0000 [id=30] INFO jenkins.InitReactorRunner$1#onAttained: System config loaded
2023-01-05 06:02:15.936+0000 [id=30] INFO jenkins.InitReactorRunner$1#onAttained: System config adapted
2023-01-05 06:02:15.936+0000 [id=30] INFO jenkins.InitReactorRunner$1#onAttained: Loaded all jobs
2023-01-05 06:02:15.937+0000 [id=30] INFO jenkins.InitReactorRunner$1#onAttained: Configuration for all jobs updated
2023-01-05 06:02:16.146+0000 [id=44] INFO hudson.model.AsyncPeriodicWork#lambda$doRun$1: Started Download metadata
2023-01-05 06:02:16.212+0000 [id=44] INFO hudson.util.Retrier#start: Attempt #1 to do the action check updates server
2023-01-05 06:02:19.033+0000 [id=28] INFO jenkins.install.SetupWizard#init:
*************************************************************
*************************************************************
*************************************************************
Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:
f8bf269a288f4cdd92710f2d41eed6a1
This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
*************************************************************
*************************************************************
*************************************************************
2023-01-05 06:03:41.112+0000 [id=44] INFO h.m.DownloadService$Downloadable#load: Obtained the updated data file for hudson.tasks.Maven.MavenInstaller
2023-01-05 06:03:41.113+0000 [id=44] INFO hudson.util.Retrier#start: Performed the action check updates server successfully at the attempt #1
2023-01-05 06:03:41.115+0000 [id=44] INFO hudson.model.AsyncPeriodicWork#lambda$doRun$1: Finished Download metadata. 84,965 ms
2023-01-05 06:03:41.912+0000 [id=30] INFO jenkins.InitReactorRunner$1#onAttained: Completed initialization
2023-01-05 06:03:41.930+0000 [id=22] INFO hudson.WebAppMain$3#run: Jenkins is fully up and running
[root@liulihui home]#
After entering the administrator password, you will enter the installation interface and select the plug-in installation method. Here we will directly install the recommended plug-in.
After the installation is complete, create an administrator account:
Enter the plug-in installation interface, connect to the Internet and wait for the plug-in installation:
perform instance configuration:
Click Save and Finish, and the Jenkins installation is complete.
Enter Jenkins, click System Management -> Plug-in Management, and perform some custom plug-in installations.
Modify the plug-in site, change the original site: https://updates.jenkins.io/update-center.json to: https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json Plugins can be downloaded faster
Make sure that the following plug-ins are installed correctly. If they are not installed, you can search and install them in the optional plug-ins:
(1) Plug-ins that manage permissions according to roles: Role-based Authorization Strategy
(2) Upload the jar packaged by Jenkins to the application server: Publish Over SSH
Installed plug-in Role-based Authorization Strategy
Installed plug-in Publish Over SSH
After the installation is complete, you need to restart jenkins. You can restart jenkins by adding restart after the connection, or use the command: docker restart container name
http://ip:9080/restart or docker restart container name (here is http://ip: 9080/restart)
5. Configure JDK and Maven
Configure the global tool through system management -> global tool configuration, the path is the path in jenkins;
jdk configuration
maven configuration
System Management -> System Configuration, find Publish Over SSH, configure the application server to be connected (in the following operations, you need to use jenkins remote ssh to connect to the application server, and deploy and run the application after construction. The username and password will cause the jar package The upload failed, and an ssh key pair needs to be generated on the application server.) Create an SSH key on
Centos 7 View: https://blog.csdn.net/liulihui1988/article/details/128590218?spm=1001.2014.3001.5502
Jenkins uses ssh You can execute remote linux scripts:
Go to System Management -> Credentials, and add the Gitee login account credentials. Next, configure the credentials of Gitee. Based on these credentials, the code can be pulled from Gitee. After
completing the filling, select the credentials and you can connect to the git warehouse normally;
All the configuration work is done, and then we can start building a project.
3. Package and deploy SpringBoot application
1. Create and execute tasks in Jenkins
After setting the task name, choose to build a free-style software project:
2. Add git credentials
Add gitee login account credentials. Next, configure the credentials of gitee, based on which the code can be pulled from gitee. (If you added a credential before, just select it here)
After filling in, select the credential, and you can connect to the git warehouse normally;
3. Add maven build
maven build
Select our maven version, then set the maven command and specify the location of the pom file:
add post-build operation steps:
Because the directory mapping has been done when running jenkins earlier, after jenkins packs the package, it will actually synchronize the package to the directory mapped by the service. So there is no need to upload the jar package here, just execute the xshell command directly, enter the directory of the jar package, and execute the jar package
shell script:
#第一步是进入到服务器中生成好的jar包的目录下
cd /mydata/jenkins_home/workspace/demo/target/
#第二步是根据jar包的名字获取运行的pid,并且将该进程杀死
ps -ef | grep demo-0.0.1-SNAPSHOT.jar | grep -v grep | awk '{printf $2}' | xargs kill -9
#执行 前加载一下环境变量,否则不会执行java -jar 命令
source /etc/profile
#最后一步就是将这个jar后台启动了,并且将日志输出到warpper.log中。
nohup java -jar demo-0.0.1-SNAPSHOT.jar >demo.log &2>1 &
#睡眠1秒
sleep 1
#输出内容,可不加
echo "启动完成>>>>"
4. Build now
After the configuration is complete, click Build Now, and you can see that the console output is successful.
Select the project package branch:
branch configuration:
the service is deployed successfully, and the test interface returns successfully: