Docker 部署
加速源
sed -e 's|^mirrorlist=|#mirrorlist=|g' \
-e 's|^#baseurl=http://dl.rockylinux.org/$contentdir|baseurl=https://mirrors.aliyun.com/rockylinux|g' \
-i.bak /etc/yum.repos.d/rocky-*.repo
dnf makecache
setenforce 0
sed -i 's#^SELINUX=.*#SELINUX=disabled#' /etc/sysconfig/selinux
systemctl stop firewalld
部署Docker
curl -o /etc/yum.repos.d/docker-ce.repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
dnf install docker-ce
Gitlab 部署
部署GitLab
# cat docker-compose.yaml
version: '3.6'
services:
gitlab:
image: gitlab/gitlab-ce:latest
container_name: gitlab
restart: always
hostname: 'gitlab'
environment:
TZ: 'Asia/Shanghai'
GITLAB_OMNIBUS_CONFIG: |
# Add any other gitlab.rb configuration here, each on its own line
external_url 'http://git.sundayhk.com'
gitlab_rails['gitlab_shell_ssh_port'] = 8022
#nginx['listen_port'] = 80
nginx['client_max_body_size'] = '2048m'
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.qq.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "sundayle@qq.com"
gitlab_rails['smtp_password'] = "bdoowbhvqywydaeh"
gitlab_rails['smtp_domain'] = "smtp.qq.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = false
gitlab_rails['smtp_tls'] = true
gitlab_rails['gitlab_email_enabled'] = true
gitlab_rails['gitlab_email_from'] = 'sundayle@qq.com'
#gitlab_rails['openssl_verify_mode'] = false
#gitlab_rails['smtp_openssl_verify_mode'] = 'none'
ports:
- '80:80'
- '8443:443'
- '8022:22' # SSH端口宿主机已占用,这里映射其他端口
volumes:
- '/data/app_data/gitlab/config:/etc/gitlab'
- '/data/app_data/gitlab/logs:/var/log/gitlab'
- '/data/app_data/gitlab/data:/var/opt/gitlab'
shm_size: '256m'
[root@gitlab ~]# docker compose up -d
获取gitlab root默认密码
[root@gitlab ~]# docker exec gitlab cat /etc/gitlab/initial_root_password | grep ^Password
Password: UCc6hQKMurkvNllkBamAkS+7DCDGxxxxxxxxx=
访问 http://git.sundayhk.com/
使用root和密码登陆
关闭注册 (帐号通过管理员添加)
禁用 Gravatar
邮件配置及测试
上面通过docker-compose.yaml 配置ENV Gitlab邮件相关变量,已经实现邮件配置。
这里也可以直接编辑容器内的gitlab.rb文件实现
[root@gitlab ~]# docker exec -it gitlab bash
root@gitlab:/# vi /etc/gitlab/gitlab.rb
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.qq.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "sundayhk@qq.com"
gitlab_rails['smtp_password'] = "bdoowbxxxxxxxxxxxxxx" # 授权码
gitlab_rails['smtp_domain'] = "smtp.qq.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = false
gitlab_rails['smtp_tls'] = true
# gitlab_rails['smtp_pool'] = false
gitlab_rails['gitlab_email_enabled'] = true
gitlab_rails['gitlab_email_from'] = 'sundayhk@qq.com'
每次修改都要重新生成配置文件及重启服务
# gitlab-rake gitlab:check
gitlab-ctl reconfigure
gitlab-ctl restart
邮件测试
root@gitlab:/# gitlab-rails console
--------------------------------------------------------------------------------
Ruby: ruby 3.1.5p253 (2024-04-023 revision 1945f8dc0e) [x86_64-linux]
GitLab: 17.2.1 (b30193cc04c) FOSS
GitLab Shell: 14.37.0
PostgreSQL: 14.11
------------------------------------------------------------[ booted in 59.20s ]
=> #<Mail::Message:513100, Multipart: false, Headers: <Date: Sat, 27 Jul 2024 13:45:40 +0000>, <From: GitLab <sundayle@qq.com>>, <Reply-To: GitLab <noreply@git.sundayhk.com>>, <To: shaopenghk@qq.com>, <Message-ID: <66a4fa04941de_11ef2ff8446b4@gitlab.mail>>, <Subject: test>, <Mime-Version: 1.0>, <Content-Type: text/html; charset=US-ASCII>, <Content-Transfer-Encoding: 7bit>, <Auto-Submitted: auto-generated>, <X-Auto-Response-Suppress: All>>
irb(main):012:0>
配置邮件后 添加新用户 则会发邮件 通过链接设置用户密码
Gitlab备份
手动备份
[root@gitlab ~]# docker exec gitlab gitlab-rake gitlab:backup:create
[root@gitlab ~]# docker exec gitlab ls /var/opt/gitlab/backups/
1722090118_2024_07_27_17.2.1_gitlab_backup.tar
宿主机定时备份任务
[root@gitlab ~]# crontab -e
# m h dom mon dow command
# gitlab backup
00 02 * * * /data/shell/gitlab_backup.sh > /dev/null 2>&1
备份脚本
[root@gitlab ~]# vim /data/shell/gitlab_backup.sh
#!/bin/bash
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
docker exec gitlab gitlab-rake gitlab:backup:create
Gitlab恢复
[root@gitlab ~]# docker exec -it gitlab bash
# 停止相关数据连接服务
root@gitlab:/# gitlab-ctl stop unicorn
root@gitlab:/# gitlab-ctl stop sidekiq
root@gitlab:/# cd /var/opt/gitlab/backups
root@gitlab:/var/opt/gitlab/backups# ls -l
total 1000
-rw-------. 1 git git 512000 Jul 27 22:22 1722090118_2024_07_27_17.2.1_gitlab_backup.tar
root@gitlab:/var/opt/gitlab/backups# gitlab-rake gitlab:backup:restore
BACKUP=1722090118_2024_07_27_17.2.1
# 启动Gitlab
root@gitlab:/var/opt/gitlab/backups# gitlab-ctl start
SonarQube Docker部署
宿主机参数配置
配置内核参数
echo vm.max_map_count=524288 >> /etc/sysctl.conf
echo fs.file-max=131072 >> /etc/sysctl.conf
sysctl -p
配置安全限制 (重新登陆终端生效)
echo "* soft nofile 131072" >> /etc/security/limits.conf
echo "* hard nofile 131072 " >> /etc/security/limits.conf
[root@jenkins ~]# mkdir -p /data/docker_yaml/sonarqube/
# cat /data/docker_yaml/sonarqube/docker-compose.yaml
version: "3"
services:
postgres:
image: postgres
container_name: postgres
restart: unless-stopped
ports:
- 5432:5432
networks:
- sonarnet
environment:
POSTGRES_DB: sonar
POSTGRES_USER: sonar
POSTGRES_PASSWORD: sonar
volumes:
- ./data/postgresql:/var/lib/postgresql
sonarqube:
image: sonarqube:9.9.6-community
container_name: sonarqube
restart: unless-stopped
ports:
- "9000:9000"
depends_on:
- db
networks:
- sonarnet
environment:
SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar
SONAR_JDBC_USERNAME: sonar
SONAR_JDBC_PASSWORD: sonar
volumes:
- ./data/sonarqube/data:/opt/sonarqube/data
- ./data/sonarqube/extensions:/opt/sonarqube/extensions
- ./data/sonarqube/logs:/opt/sonarqube/logs
networks:
sonarnet:
driver: bridge
挂载因权限问题需要修改用户权限再重新启动
[root@jenkins sonarqube]# docker compose up -d
[root@jenkins sonarqube]# chown -R 999:999 ./data/postgresql/
[root@jenkins sonarqube]# chown -R 1000:1000 ./data/sonarqube/
[root@jenkins sonarqube]# docker compose down
[root@jenkins sonarqube]# docker compose up -d
启动容器后观察日志是否正常启动
[root@jenkins sonarqube]# docker compose logs -f
# 看到如下内容代表启动成功
2024.08.26 07:03:33 INFO ce[][o.s.p.ProcessEntryPoint] Starting Compute Engine
2024.08.26 07:03:33 INFO ce[][o.s.ce.app.CeServer] Compute Engine starting up...
2024.08.26 07:03:34 INFO ce[][o.sonar.db.Database] Create JDBC data source for jdbc:postgresql://db:5432/sonar
2024.08.26 07:03:34 INFO ce[][c.z.h.HikariDataSource] HikariPool-1 - Starting...
2024.08.26 07:03:35 INFO ce[][c.z.h.p.HikariPool] HikariPool-1 - Added connection org.postgresql.jdbc.PgConnection@62138e8d
2024.08.26 07:03:35 INFO ce[][c.z.h.HikariDataSource] HikariPool-1 - Start completed.
2024.08.26 07:03:37 INFO ce[][o.s.s.p.ServerFileSystemImpl] SonarQube home: /opt/sonarqube
2024.08.26 07:03:37 INFO ce[][o.s.c.c.CePluginRepository] Load plugins
2024.08.26 07:03:41 INFO ce[][o.s.c.c.ComputeEngineContainerImpl] Running Community edition
2024.08.26 07:03:41 INFO ce[][o.s.ce.app.CeServer] Compute Engine is started
2024.08.26 07:03:42 INFO app[][o.s.a.SchedulerImpl] Process[ce] is up
2024.08.26 07:03:42 INFO app[][o.s.a.SchedulerImpl] SonarQube is operational
正常启动后在浏览器打开http://ip:9090, 用户名密码默认admin
这里启动有点慢,耐心等待
安装中文
重启SonarQube 生效
注意:SonarQube根据浏览器的header选择显示的语言,如果安装中文插件重启后还是显示英文,一般是因为浏览器选择了英文。需将中文置顶。
Maven安装
测试使用 选择性安装
安装 JDK 17
该版本兼容Maven和SonarQube
https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html
[root@jenkins ~]# wget https://download.oracle.com/java/17/archive/jdk-17.0.7_linux-x64_bin.tar.gz
[root@jenkins ~]# tar xf jdk-17.0.7_linux-x64_bin.tar.gz
[root@jenkins ~]# jdk-17.0.11 /usr/local/jdk
配置JDK环境变量
[root@jenkins ~]# cat > /etc/profile.d/jdk.sh << \EOF
# set oracle jdk environment
export JAVA_HOME=/usr/local/jdk
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
EOF
[root@jenkins ~]# source /etc/profile.d/jdk.sh
查看JDK版本
[root@jenkins ~]# java -version
java version "17.0.11" 2024-04-16 LTS
Java(TM) SE Runtime Environment (build 17.0.11+7-LTS-207)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.11+7-LTS-207, mixed mode, sharing)
安装Maven
[root@jenkins ~]# wget https://dlcdn.apache.org/maven/maven-3/3.8.8/binaries/apache-maven-3.8.8-bin.tar.gz
[root@jenkins ~]# tar xf apache-maven-3.8.8-bin.tar.gz
[root@jenkins ~]# mv apache-maven-3.8.8 /usr/local/maven
配置Maven环境变量
[root@jenkins ~]# cat > /etc/profile.d/maven.sh << \EOF
export JAVA_HOME=/usr/local/jdk
export MAVEN_HOME=/usr/local/maven
export PATH=${MAVEN_HOME}/bin:${JAVA_HOME}/bin:$PATH
EOF
查看Maven版本信息
[root@jenkins ~]# source /etc/profile.d/maven.sh
[root@jenkins ~]# mvn -v
Apache Maven 3.8.8 (4c87b05d9aedce574290d1acc98575ed5eb6cd39)
Maven home: /usr/local/maven
Java version: 17.0.11, vendor: Oracle Corporation, runtime: /usr/local/jdk
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "5.14.0-362.8.1.el9_3.x86_64", arch: "amd64", family: "unix"
配置Maven镜像加速
[root@jenkins ~]# vim /usr/local/maven/conf/settings.xml
<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
SonarQube 使用
SonarQube的使用方式很多,Maven可以整合,也可以采用sonar-scanner的方式,再查看Sonar Qube的检测效果
Maven实现代码检测
maven/conf/settings.xml 配置sonarqube
<profile>
<id>sonar</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<sonar.login>admin</sonar.login>
<sonar.password>123456789</sonar.password>
<sonar.host.url>http://192.168.77.17:9000</sonar.host.url>
</properties>
</profile>
项目代码
git clone https://github.com/sundayhk/spring-boot-hello-world.git
cd spring-boot-hello-word
项目代码 pod.xml 添加插件 (这里已经添加了)
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
</plugin>
在项目代码位置执行命令:
mvn package
mvn sonar:sonar
SonarScanner使用
SonarQube配置令牌
复制生成的令牌 squ_cc848f66bf8b0da638e7e87cef3e53777775d85d
sonar-scanner安装
[root@jenkins ~]# wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-6.1.0.4477-linux-x64.zip
[root@jenkins ~]# unzip sonar-scanner-cli-6.1.0.4477-linux-x64.zip
[root@jenkins ~]# mv sonar-scanner-cli-6.1.0.4477-linux-x64 /usr/local/sonar-scanner
sonar-scanner配置文件
[root@jenkins ~]# vim /usr/local/sonar-scanner/conf/sonar-scanner.properties
# Configure here general information about the environment, such as the server connection details for example
# No information about specific project should appear here
#----- SonarQube server URL (default to SonarCloud)
sonar.host.url=http://192.168.77.16:9000
#sonar.scanner.proxyHost=myproxy.mycompany.com
#sonar.scanner.proxyPort=8002
sonar.sourceEncoding=UTF-8
sonar-scanner代码检测
[root@jenkins ~]# git clone https://github.com/sundayhk/spring-boot-hello-world.git
[root@jenkins ~]# cd spring-boot-hello-world
[root@jenkins spring-boot-hello-world]# ls
docker-compose.yaml Dockerfile pom.xml README.md src target
[root@jenkins spring-boot-hello-world]# mvn package
[root@jenkins spring-boot-hello-world]# /usr/local/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=spring-boot-hello-world -Dsonar.projectKey=java -Dsonar.java.binaries=target/ -Dsonar.login=squ_cc848f66bf8b0da638e7e87cef3e53777775d85d
...
01:35:18.458 INFO ANALYSIS SUCCESSFUL, you can find the results at: http://192.168.77.16:9000/dashboard?id=spring-boot-hello-world
01:35:18.458 INFO Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report
01:35:18.460 INFO More about the report processing at http://192.168.77.16:9000/api/ce/task?id=AZG2YVeR2fyEPGXMqRUB
01:35:18.482 INFO Analysis total time: 10.707 s
01:35:18.485 INFO EXECUTION SUCCESS
01:35:18.486 INFO Total time: 13.401s
Jenkins 自由风格部署
Jenkins配置
代码拉取到Jenkins本地后,需要在Jenkins中对代码进行构建,这里需要Maven的环境,而Maven需要Java的环境,接下来需要在Jenkins中安装JDK和Maven,并且配置到Jenkins服务。
[root@jenkins ~]# docker pull jenkins/jenkins:lts
[root@jenkins ~]# mkdir -p /data/docker_yaml/jenkins
[root@jenkins jenkins]# cd /data/docker_yaml/jenkins
Jenkins容器内JDK版本为17 (/opt/java/openjdk),若需要指定版本则需安装或挂载
这里使用JDK11
[root@jenkins jenkins]# wget https://aka.ms/download-jdk/microsoft-jdk-11.0.24-linux-x64.tar.gz
[root@jenkins jenkins]# tar xf microsoft-jdk-11.0.24-linux-x64.tar.gz
Jenkins容器内Maven准备,JAVA项目构建使用
[root@jenkins jenkins]# wget https://dlcdn.apache.org/maven/maven-3/3.8.8/binaries/apache-maven-3.8.8-bin.tar.gz
[root@jenkins jenkins]# tar xf apache-maven-3.8.8-bin.tar.gz
中央仓库加速
[root@jenkins jenkins]# vim ./apache-maven-3.8.8/conf/settings.xml
<mirrors>
<!-- 阿里云加速--!>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
复制前面配置的sonar-scanner目录
[root@jenkins jenkins]# cp -r /usr/local/sonar-scanner .
# vim /data/docker_yaml/jenkins/docker-compose.yaml
version: "3"
services:
jenkins:
image: jenkins/jenkins:lts
container_name: jenkins
restart: on-failure
environment:
TZ: Asia/Shanghai
ports:
- 8080:8080
- 50000:50000
volumes:
- ./data/jenkins_home:/var/jenkins_home
- ./apache-maven-3.8.8:/usr/local/maven
- ./jdk-11.0.24+8:/usr/local/jdk
- ./sonar-scanner:/usr/local/sonar-scanner
[root@jenkins jenkins]# mkdir -p ./data/jenkins_home
[root@jenkins jenkins]# chown 1000:1000 ./data/jenkins_home
[root@jenkins jenkins]# docker compose up -d
查看jenkins密钥
[root@jenkins jenkins]# docker exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword
# 或查看日志
[root@jenkins jenkins]# docker compose logs
...
jenkins |
jenkins | e531c57c3e6e47f4a8b055ee608ad51c
jenkins |
jenkins | This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
修改jenkins更新源
Jenkins安装过程需要下载插件,但是默认下载地址下载速度较慢,需要更新下载地址为国内镜像站
如华为云源加速
https://www.jenkins-zh.cn/tutorial/management/mirror/
直接在物理机修改数据卷文件
[root@jenkins jenkins]# vim /data/app_data/jenkins_home/hudson.model.UpdateCenter.xml
<?xml version='1.1' encoding='UTF-8'?>
<sites>
<site>
<id>default</id>
<url>https://mirrors.huaweicloud.com/jenkins/updates/update-center.json</url>
</site>
</sites>
修改后 重启下Jenkins容器
[root@jenkins jenkins]# docker compose restart
访问:http:///IP:8080
输入密钥
选择第二个
默认
安装插件
中文插件 新版翻译不全,但够用 安装过locale插件 zh_cn设置无效,zh_tw则正常
- Localization: Chinese(Simplified)
需要重启才生效
浏览器访问: http://192.168.77.16:8080/restart
注:若Docker部署没指定重启策略(默认no), 不会自动拉起容器,此时执行 浏览器重启jenkins,则容器状态是退出状态,需手动启动容器或指定重启策略为 always、on-failure、unless-stopped,容器内重启jenkins才会自动重启容器
- Git Parameter
- Publish Over SSH
- Gitlab SSH 密钥
生成SSH密钥对
[root@jenkins ~]# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:pT7dOlOcFLxGQbwovGzKxQ2X+UxfFy3vee12ng999vI root@jenkins
The key's randomart image is:
...
[root@jenkins ~]# ls -l .ssh/
total 12
-rw-------. 1 root root 2602 Aug 31 03:23 id_rsa
-rw-r--r--. 1 root root 566 Aug 31 03:23 id_rsa.pub
-rw-r--r--. 1 root root 92 Aug 28 01:48 known_hosts
Gitlab 添加SSH密钥 粘贴 id_rsa.pub 内容
Jenkins 全局凭据 添加 Gitlab SSH密钥
Gitlab 创建 Access Token (到期时间限制最长为一年)
系统管理-系统配置 找到Gitlab
添加后 选中 保存
系统管理-全局工具配置
JDK配置
Maven配置
项目部署
这里先构建自由风格的软件项目,方便入门,后续主要使用流水线,其实都挺简单。
java项目:https://github.com/sundayhk/spring-boot-hello-world
前面已经配置了Gitlab SSH 密钥
增加构建步骤
构建测试
配置好了 点击 立即构建
查看最近一次构建
查看控制台输出 拉到最底部 查看构建结果
构建Success
进入Jenkins目录 可以看到targetr下打包好的 spring-boo-hello-world-1.0.2.jar
[root@jenkins ~]# docker exec -it jenkins bash
jenkins@e95cee752a96:/$ ls -l /var/jenkins_home/workspace/spring-boot-hello-world/target/
total 17408
drwxr-xr-x. 3 jenkins jenkins 47 Sep 1 11:39 classes
drwxr-xr-x. 3 jenkins jenkins 25 Sep 1 11:39 generated-sources
drwxr-xr-x. 3 jenkins jenkins 30 Sep 1 11:39 generated-test-sources
drwxr-xr-x. 2 jenkins jenkins 28 Sep 1 11:40 maven-archiver
drwxr-xr-x. 3 jenkins jenkins 35 Sep 1 11:39 maven-status
-rw-r--r--. 1 jenkins jenkins 17813960 Sep 1 11:41 spring-boot-hello-world-1.0.2.jar
-rw-r--r--. 1 jenkins jenkins 3589 Sep 1 11:40 spring-boot-hello-world-1.0.2.jar.original
drwxr-xr-x. 2 jenkins jenkins 4096 Sep 1 11:40 surefire-reports
drwxr-xr-x. 3 jenkins jenkins 17 Sep 1 11:39 test-classes
持续集成Publish Over SSH
插件:Publish Over SSH
Jenkins拉取GitLab的SpringBoot代码进行构建发布到测试环境实现持续集成
配置Publish Over SSH,将构建好的JAR包,传输到测试或生产服务器,进行Docker自动部署运行
系统管理-系统配置-Publish over SSH
配置测试服务器 强烈建议使用密钥
Docker文件
# cat Dockerfile
FROM openjdk:8-jdk-alpine
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
# docker-compose.yaml
version: "3.8"
services:
spring-boot-hello-world:
build:
context: ./
#dockerfile: Dockerfile
#args:
# - JAR_FILE=target/*.jar
image: spring-boot-hello-world:v1.0.0
container_name: spring-boot-hello-world
ports:
- 8888:8080
Jenkins构建后操作脚本命令
持续集成SonarQube
插件:SonarQube Scanner
Sonar Qube 开启权限验证
Sonar Qube 配置令牌
Jenkins 全局凭据 配置SonarQube Token
SonarQube Token 凭据需提前创建
Jenkins 配置sonar-scanner
配置项目工程
Analysis properties
sonar.projectname=${JOB_NAME}
sonar.projectKey=${JOB_NAME}
sonar.source=./
sonar.java.binaries=target/
点击构建
控制台输出结果
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.187 s
[INFO] Finished at: 2024-09-03T14:11:11+08:00
[INFO] ------------------------------------------------------------------------
SSH: Connecting from host [5d78ad8df758]
SSH: Connecting with configuration [TestServer] ...
SSH: EXEC: completed after 19,418 ms
SSH: Disconnecting configuration [TestServer] ...
SSH: Transferred 4 file(s)
Finished: SUCCESS
持续交付Git Parameter
插件:Git Parameter
基于Git Parameter 选取指定的发行版本构建任务,交付发布到目标服务器
配置工程
添加Git参数
构建步骤
删除之前配置的调用顶层Maven目标,添加执行Shell
cd ${WORKSPACE}
git checkout $release
rm -rf target/*
/usr/local/maven/bin/mvn package -DskipTests
修改代码 打下tag
[root@jenkins spring-boot-hello-world]# vim src/main/java/com/example/helloworld/controller/HelloWorldController.java
package com.example.helloworld.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloWorldController {
@GetMapping("/")
public String sendGreetings() {
return "Hello World! V1.0.0"; // 修改
}
}
修改内容并打标签
[root@jenkins spring-boot-hello-world]# git commit -m 'update release to v1.0.0'
[root@jenkins spring-boot-hello-world]# git tag v1.0.0
[root@jenkins spring-boot-hello-world]# git push origin v1.0.0
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
To ssh://git.sundayhk.com:8022/zsp/spring-boot-hello-world.git
* [new tag] v1.0.0 -> v1.0.0
构建任务成功 查看
[root@jenkins spring-boot-hello-world]# curl 192.168.77.16:8888
Hello World! V1.0.0
推送镜像仓库
Jenkins容器使用宿主机Docker
构建镜像和发布镜像到harbor都需要使用到docker命令。而在Jenkins容器内部安装Docker官方推荐直接采用宿主机带的Docker即可。
若宿主机Docker是用root启动的,而 Jenkins容器 默认用户是 jenkins,id 和 group 都是 1000(官方容器默认的值),这种情况在容器中就无法正常写入文件到宿主机,会报Permission denied
设置宿主机docker.sock权限:
chown 1000:1000 /var/run/docker.sock
# 或
chmod 666 /var/run/docker.sock
添加数据卷
# cat docker-compose.yaml
version: "3"
services:
jenkins:
image: jenkins/jenkins:lts
container_name: jenkins
restart: on-failure
environment:
TZ: Asia/Shanghai
ports:
- 8080:8080
- 50000:50000
volumes:
- ./data/jenkins_home:/var/jenkins_home
- ./apache-maven-3.8.8:/usr/local/maven
- ./jdk-11.0.24+8:/usr/local/jdk
- ./sonar-scanner:/usr/local/sonar-scanner
docker compose up -d
添加构建步骤
docker build -t harbor.sundayhk.com/java_project/${JOB_NAME}:$tag ./
docker login -u admin -p password harbor.sundayhk.com
docker push harbor.sundayhk.com/java_project/${JOB_NAME}:$tag
[root@jenkins ~]# docker images | grep harbor.sundayhk.com/java_project/spring-boot-hello-world
harbor.sundayhk.com/java_project/spring-boot-hello-world v1.0.0 18449e7172b1 1 minute ago 672MB
编写部署脚本
部署项目需要通过Publish Over SSH插件,让目标服务器执行命令。为了方便一次性实现拉取镜像和启动的命令,推荐采用脚本文件的方式。
添加脚本文件到目标服务器,再通过Publish Over SSH插件让目标服务器执行脚本即可。
系统管理 - 系统配置 Publish over SSH 添加服务器
如生产服务器禁用Root登陆,则普通用户需要加入sudo 无密码
#visudo
sunday ALL=(ALL:ALL) NOPASSWD:ALL
重新登陆终端才生效
测试
sudo cat /etc/shadow
将deploy.sh 脚本放到 prod server服务器 /data/shell下
# deploy.sh
#!/bin/bash
harbor_url=$1
harbor_project_name=$2
project_name=$3
tag=$4
host_port=$5
container_port=$6
harbor_user="admin"
harbor_password="password"
if [ $# -lt 6 ]; then
echo "Usg: $0 <harbor_url> <harbor_project_name> <project_name> <tag> <host_port> <container_port>"
exit 1
fi
image_name=$harbor_url/$harbor_project_name/$project_name:$tag
container_id=`docker ps -a | grep ${project_name} | awk '{print $1}'`
image_id=`docker images | grep ${project_name} | awk '{print $3}'`
if [ "$container_id" != "" ] ; then
docker stop $container_id
docker rm $container_id
fi
if [ "$image_id" != "" ] ; then
docker rmi -f $image_id
fi
if ! docker login -u $harbor_user -p $harbor_password $harbor_url; then
echo "harbor login fail"
exit 1
fi
if ! docker pull $image_name; then
echo "imgage pull fail"
exit 1
fi
if ! docker run -d -p $host_port:$container_port --name $project_name $image_name; then
echo "container run fail"
exit 1
fi
echo "$0 run success!"
chmod +x deploy.sh
sudo /data/shell/deploy.sh harbor.sundayhk.com java_project ${JOB_NAME} $tag $host_port $container_port > /var/log/deploy.log
[root@rancher shell]# docker ps -a | grep spring-boot
f38d87da58f9 harbor.sundayhk.com/java_project/spring-boot-hello-world:v1.0.0 "java -jar /app.jar" 34 seconds ago Up 33 seconds 0.0.0.0:8081->8080/tcp, :::8081->8080/tcp spring-boot-hello-world
Jenkins pipeline部署
Jenkins流水线任务
Jenkins的自由风格构建的项目,每个步骤流程都要通过不同的方式设置,并且构建过程中整体流程是不可见的,无法确认每个流程花费的时间,并且问题不方便定位问题。
Jenkins的Pipeline可以让项目的发布整体流程可视化,明确执行的阶段,可以快速的定位问题。并且整个项目的生命周期可以通过一个Jenkinsfile文件管理,而且Jenkinsfile文件是可以放在项目中维护。所以Pipeline相对自由风格或者其他的项目风格更容易操作。
新建任务 Jenkins流水线
生成Groovy脚本
项目发行 选择版本标签
参数化构建
构建参数,配置tag标签
配置端口参数
流水线语法生成
拉取Git代码 选择Git参数定义tag标签
流水线语法git checkout 生成为简化代码 不支持动态选择标签,则修改成如下
checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[credentialsId: 'be7a22f2-4859-4562-a720-eaed300e29ed', url: 'ssh://git@git.sundayhk.com:8022/zsp/spring-boot-hello-world.git']]])
配置pipeline
这里将Jenkinsfile 放在代码仓库中
注:由于采用变量,记得使用双引号
如 sshPublisher 中的execCommand
配置 Harbor 账户凭据
生成流水线语法
pipeline {
agent any
environment{
harbor_host = 'harbor.sundayhk.com'
harbor_repo = 'java_project'
harbor_id = '7045de0f-8aa4-4ac5-905c-b4cab45f74cf'
}
stages {
stage('拉取Git代码') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[credentialsId: 'be7a22f2-4859-4562-a720-eaed300e29ed', url: 'ssh://git@git.sundayhk.com:8022/zsp/spring-boot-hello-world.git']]])
}
}
stage('构建代码') {
steps {
sh '/usr/local/maven/bin/mvn clean package -DskipTests'
}
}
stage('检测代码质量') {
steps {
sh '/usr/local/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.java.binaries=target/ -Dsonar.login=squ_427af7410ee605dc171c84dabb09c9fea06e9164'
}
}
stage('制作自定义镜像并发布Harbor') {
steps {
sh '''docker build -t ${JOB_NAME}:${tag} ./'''
withCredentials([usernamePassword(credentialsId: "${harbor_id}", passwordVariable: 'password', usernameVariable: 'username')]) {
sh '''docker login -u ${username} -p ${password} ${harbor_host}
docker tag ${JOB_NAME}:${tag} ${harbor_host}/${harbor_repo}/${JOB_NAME}:${tag}
docker push ${harbor_host}/${harbor_repo}/${JOB_NAME}:${tag}'''
}
}
}
stage('目标服务器拉取镜像并运行') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'TestServer', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/data/shell/deploy.sh ${env.harbor_host} ${env.harbor_repo} ${JOB_NAME} $tag $host_port $container_port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: true)])
}
}
}
}
钉钉通知
插件:DingTalk
复制Webhook信息
https://oapi.dingtalk.com/robot/send?access_token=1fc63b1d066a56cc04a8261ba61cbb1362cea2a3e9ae9c9167ae8e98fc64f065
JenkinsFile
pipeline {
agent any
environment{
harbor_host = 'harbor.sundayhk.com'
harbor_repo = 'java_project'
harbor_id = '7045de0f-8aa4-4ac5-905c-b4cab45f74cf'
}
stages {
stage('拉取Git代码') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[credentialsId: 'be7a22f2-4859-4562-a720-eaed300e29ed', url: 'ssh://git@git.sundayhk.com:8022/zsp/spring-boot-hello-world.git']]])
}
}
stage('构建代码') {
steps {
sh '/usr/local/maven/bin/mvn clean package -DskipTests'
}
}
stage('检测代码质量') {
steps {
sh '/usr/local/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.java.binaries=target/ -Dsonar.login=squ_427af7410ee605dc171c84dabb09c9fea06e9164'
}
}
stage('制作自定义镜像并发布Harbor') {
steps {
sh '''docker build -t ${JOB_NAME}:${tag} ./'''
withCredentials([usernamePassword(credentialsId: "${harbor_id}", passwordVariable: 'password', usernameVariable: 'username')]) {
sh '''docker login -u ${username} -p ${password} ${harbor_host}
docker tag ${JOB_NAME}:${tag} ${harbor_host}/${harbor_repo}/${JOB_NAME}:${tag}
docker push ${harbor_host}/${harbor_repo}/${JOB_NAME}:${tag}'''
}
}
}
stage('目标服务器拉取镜像并运行') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'TestServer', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/data/shell/deploy.sh ${env.harbor_host} ${env.harbor_repo} ${JOB_NAME} $tag $host_port $container_port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: true)])
}
}
}
post {
success {
dingtalk (
robot: 'DingTalk-Bot',
type:'MARKDOWN',
title: "success: ${JOB_NAME}",
text: ["- 成功构建:${JOB_NAME}项目!\n- 版本:${tag}\n- 持续时间:${currentBuild.durationString}\n- 任务:#${JOB_NAME}"]
)
}
failure {
dingtalk (
robot: 'DingTalk-Bot',
type:'MARKDOWN',
title: "fail: ${JOB_NAME}",
text: ["- 失败构建:${JOB_NAME}项目!\n- 版本:${tag}\n- 持续时间:${currentBuild.durationString}\n- 任务:#${JOB_NAME}"]
)
}
}
}