【百练成魔】Jenkins CI/CD
架构 Jenkins + Gitlab + Docker + Harbor + Maven + SonarQube
流程图

服务器准备
虚拟机虚拟化出一台 4C 16G 80G 服务器 本次所有项目均使用Docker部署都在单节点运行,也可以拆解分配项目
安装docker
关闭firewalld seliunx防火墙
1
| systemctl stop firewalld && systemctl disable firewalld && setenforce 0
|
安装docker及docker-compose
安装必要系统工具
1
| yum install -y yum-utils device-mapper-persistent-data lvm2
|
添加软件源信息
1
| yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
|
安装docker
1
| yum -y install docker-ce
|
安装docker-compose
仓库地址
1
| https://github.com/docker/compose/releases
|
下载compose // 由于github是国外的所以可能下载失败 需要多试几次,或使用主机开启魔法下载
1
| wget https://github.com/docker/compose/releases/download/v2.20.2/docker-compose-linux-x86_64
|
1 2
| chmod +x docker-compose-linux-x86_64 mv docker-compose-linux-x86_64 /usr/bin/docker-compose
|

启动docker 并设置开机自启 检查版本
1 2 3 4 5
| systemctl start docker systemctl enable docker
docker docker-compose
|

到这里docker,docker-compose安装完毕
安装gitlab
使用docker-compose部署
拉取镜像
1
| docker pull gitlab/gitlab-ce
|
创建gitlab目录,使用本目录作为gitlab挂载目录存放数据文件
1 2
| mkdir /usr/local/gitlab cd /usr/local/gitlab
|
准备docker-compose文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| version: '3.1' services: gitlab: image: 'gitlab/gitlab-ce:latest' container_name: gitlab restart: always environment: GITLAB_OMNIBUS_CONFIG: | external_url 'http://192.168.117.141:8929' ##修改为宿主机IP gitlab_rails['gitlab_shell_ssh_port'] = 2224 ports: - '8929:8929' - '2224:2224' volumes: - './config:/etc/gitlab' - './logs:/var/log/gitlab' - './data:/var/opt/gitlab'
|
启动容器
查看是否启动

访问IP:8929 若出现502则需要继续等待初始化一会
查看初始化root密码
1
| docker exec -it gitlab cat /etc/gitlab/initial_root_password
|

登录gitlab

修改密码 点击头像

点击 preferences

点击 password 修改完点击 Save password 保存

保存后会退出 重新登录就可以了 使用你设置的新密码

点击首页 Create a projeck
创建新项目

创建空白仓库

创建空仓库

推送代码到仓库
安装git 用来拉取仓库
仓库点击clone 复制 http拉取代码方式

回到用户家目录 拉取代码
1 2
| cd git clone http://192.168.117.141:8929/root/devops-test.git
|
配置git推送用户名及邮箱 ##随便写就可
1 2
| git config --global user.name "Administrator" git config --global user.email "admin@example.com"
|
进入目录并切换到main分支
1 2
| cd /devops-test/ git checkout -b main
|
拉取我在gitee放的代码
1
| git clone https://gitee.com/jd_688/hell.git -b main
|
移动gitee代码到 当前目录下 并删除gitee目录
1 2
| mv hell/* ./ rm -rf hell/
|

提交代码到gitlab仓库
1 2 3
| git add * git commit -m "推送代码" git push -u origin main
|
输入gitlab账号密码 即可推送成功 # 若密码输入错误可再次执行 git push -u origin main 推送命令

回到仓库点击刷新就可以看到推送上来的代码

安装Jenkins
创建jenkins目录及数据持久化目录
1 2
| mkdir /usr/local/jenkins cd /usr/local/jenkins
|
拉取Jenkins镜像
1
| docker pull jenkins/jenkins
|
编写启动docker-compose文件
1 2 3 4 5 6 7 8 9 10 11
| version: "3.1" services: jenkins: image: jenkins/jenkins container_name: jenkins restart: always ports: - 8080:8080 - 50000:50000 volumes: - ./data/:/var/jenkins_home/
|
启动Jenkins容器

第一次启动会启动失败 是因为对数据库data没有读权限 我们加一下就可以了

再次启动jenkins容器

先修改插件下载源,不然使用默认源会下载失败也很慢
1 2
| cd /data vim vim hudson.model.UpdateCenter.xml
|
1 2 3 4 5 6 7
| <?xml version='1.1' encoding='UTF-8'?> <sites> <site> <id>default</id> <url>http://mirror.esuni.jp/jenkins/updates/update-center.json</url> </site> </sites>
|

再次重启Jenkins容器,访问JenKins:IP:8080/restart 弹出界面点击yes
例如我的机器是


这时就可以正常使用了 访问IP:8080 进入jenkins的操作页面

获取密码
1
| docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
|

输入密码点击继续
选择插件来安装

搜索这个选择上 点击安装

等待安装完成,耗时会有点长,待会进入系统再去安装其他所用插件
安装完成后会自动跳转界面 设置新密码即可

这个默认的即可 我们就是IP:8080访问 所以不需要修改

保存开始 使用Jenkins

到这里我们就算是部署Jenkins完毕 ,下面开始配工程

创建后进入配置 选择源码管理 Git

公开仓库http配置
回到gitlab仓库复制仓库地址

填入仓库地址看到没有报错 指定分支 填写我们创建的 main分支 点击保存即可

私有仓库http配置
公开的仓库直接跳过这一步
私有仓库直接填写地址 下面会出现红色报错 让你提供认证秘钥 我这里是公开仓库所以是没有显示的
配置密码的方式如下,配置秘钥这里就不写了


添加选择就可以了 并修改指定配置为 main分支

继续我们先使用jenkins拉取代码
点击构建 完成出现绿色对号

也可以点击#2 点击控制台输出 查看日志 我是构建过一次所以是2# 第一构建的话都是1#

看到日志说 我们已经把代码拉取下来了 我们到服务器查看一下
这里目录/devops-test 就是jenkins创建工程的名字
1 2
| cd /usr/local/jenkins/data/workspace/devops-test ls
|
可以看到代码已经拉取到服务器了

接下来使用maven打包代码为jar包
配置jdk 和 maven
1 2 3
| 下载地址 jdk https://d6.injdk.cn/openjdk/openjdk/17/openjdk-17.0.1_linux-x64_bin.tar.gz maven https://dlcdn.apache.org/maven/maven-3/3.9.4/binaries/apache-maven-3.9.4-bin.tar.gz
|
下载完上传到服务器/root目录
解压到Jenkins挂载目录让Jenkins使用
1 2 3 4 5
| tar xf apache-maven-3.9.4-bin.tar.gz -C /usr/local/jenkins/data/ tar xf openjdk-17.0.1_linux-x64_bin.tar.gz -C /usr/local/jenkins/data/ cd /usr/local/jenkins/data/ mv apache-maven-3.9.4/ maven mv jdk-17.0.1/ jdk17
|
此时容器中/var/jenkins_home中 maven和jdk17 已经挂载进来了

修改maven配置文件
1
| vim /usr/local/jenkins/data/maven/conf/settings.xml
|
改为以下内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd"> <pluginGroups> </pluginGroups> <proxies> </proxies> <servers> </servers>
<mirrors> <mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror> </mirrors>
<profiles> </profiles>
</settings>
|
点击Dashboard 回到首页 点击Manage Jenkins

点击Tookl 配置全局配置

往下拉 看到maven安装


**点击保存 回到主页 选择devops-test这个工程 **

配置 Build Steps
调用顶层Maven目录 选择maven 目标输入下面内容 点击保存

再次构建 点击开始构建 首次编译需要下载插件所以需要时间会有点长
点击2# 点击控制台输出 查看日志

Build Success表示打包完成
查看jar包
1 2
| cd /usr/local/jenkins/data/workspace/devops-test ls target/
|

使用Java 运行跑一下
1
| /usr/local/jenkins/data/jdk17/bin/java -jar target/testinit-0.0.1-SNAPSHOT.jar
|

浏览器访问IP:9901

看完以后就可以 ctrl +c 取消运行jar包
配置Git参数化构建
回到工程 配置

看图配置 把构建操作×掉

重新选择执行shell

1 2 3
| cd /var/jenkins_home/workspace/${JOB_NAME} git checkout $tag /var/jenkins_home/maven/bin/mvn clean package
|
1 2 3 4
| 参数解释
${JOB_NAME} 为当前工程名字 也就是devops-test $tag 就是上面配置tag标签
|
点击保存
回到仓库目录 修改代码 作为标识
1 2
| cd /root/devops-test vim src/main/java/com/example/testinit/controller/HelloWord.java
|

修改完 推送代码
1 2 3 4
| git add * git commit -m " create v1.0.0" git tag -a v1.0.0 -m "create v1.0.0" git push -u origin v1.0.0
|

刷新仓库 点击tag 可以看到v1.0.0已经推送上来了


回到Jenkins项目中 点击Build 可以看到tag版本已经出来了 选中v1.0.0 开始构建

查看工程的控制台输出

再次查看jar包
1 2
| cd /usr/local/jenkins/data/workspace/devops-test ls target/
|

使用Java 运行跑一下
1
| /usr/local/jenkins/data/jdk17/bin/java -jar target/testinit-0.0.1-SNAPSHOT.jar
|

浏览器访问IP:9901

可以看到 V1.0.0已经出来了 ctrl+c 取消运行
安装SonarQube
拉取镜像
1 2
| docker pull postgres docker pull sonarqube:8.9.3-community
|
创建SonarQube目录
1 2
| mkdir /usr/local/sonarQube cd /usr/local/sonarQube
|
编写docker-compose启动文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| version: "3.1" services: db: image: postgres container_name: db ports: - 5432:5432 networks: - sonarnet environment: POSTGRES_USER: sonar POSTGRES_PASSWORD: sonar sonarqube: image: sonarqube:8.9.3-community container_name: sonarqube depends_on: - db ports: - "9000:9000" networks: - sonarnet environment: SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar SONAR_JDBC_USERNAME: sonar SONAR_JDBC_PASSWORD: sonar networks: sonarnet: driver: bridge
|
修改系统文件最大打开数量
1
| vm.max_map_count = 262144
|
刷新

启动sonar

启动需要一会时间
访问IP:9000

登录进去需要重新修改密码

修改语言为中文 第三部 I understand the resk 允许后 chinses pack 后面会出现install 点击安装即可

安装完需要重启 弹出的页面 Restart Server

再次登录进来就是中文

手动Sonar-scanner实现代码检测
下载 上传到/root
1
| https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.2.2472.zip
|
解压
1 2 3
| yum -y install unzip unzip sonar-scanner-cli-4.6.2.2472.zip mv sonar-scanner-4.6.2.2472/ /usr/local/jenkins/data/sonar-scanner
|
修改配置
1
| vim /usr/local/jenkins/data/sonar-scanner/conf
|
取消注释 改为主机IP

使用手动命令检测代码
配置Java环境
1 2 3 4
| export JAVA_HOME=/usr/local/jenkins/data/jdk17 export PATH=$PATH:$JAVA_HOME/bin export MAVEN_HOME=/usr/local/jenkins/data/maven export PATH=$PATH:$MAVEN_HOME/bin
|

1 2
| java -version mvn -version
|


获取令牌

进入工程目录
1
| cd /usr/local/jenkins/data/workspace/devops-test
|
1
| /usr/local/jenkins/data/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsona.projectname=devops-test -Dsonar.projectKey=devops-test -Dsonar.java.binaries=target/ -Dsonar.login=fe2bb1043bd317199a3919c8d78d05fc2daa4d4c
|
1 2 3 4 5 6
| 参数解释 sonar.sources=./ #指定目录 sona.projectname=devops-test #指定工程名 sonar.projectKey=devops-test #指定sonar项目名 sonar.java.binaries=target/ #指定检测jar包存放目录 sonar.login=fe2bb1043bd317199a3919c8d78d05fc2daa4d4c #指定sonar生成的秘钥
|


检查完成 回到
sonar

这样就可以看到代码的检查详情 这个开发看就行 我们不需要看
Jenkins 调用Sonar-scaner自动检测
系统管理,插件管理 安装以下插件

系统管理,全局工具管理
sonarqube scanner
取消自动安装输入容器中的sonarqube目录 点击保存
1
| /var/jenkins_home/sonar-scanner
|

系统管理,System 中 添加Sonarqube servers


来到工程项目中 构建中 增加构建步骤,选中 Execute SonarQube Scanner

1 2 3 4
| sonar.projectname=${JOB_NAME} sonar.projectKey=${JOB_NAME} sonar.source=./ sonar.java.binaries=target/
|

保存后 开始构建
这时会报错因为我们手动检测过一次 会生成一个目录,这个用户对这个目录没有写权限我们去删掉即可

1 2 3
| cd /usr/local/jenkins/data/workspace/devops-test ls -a rm -rf .scannerwork/
|

再次构建查看输出日志 已经检测完成

来到Sonarqube的web界面中查看 这样就OK了

安装Harbor仓库
下载安装包
1
| https://github.com/goharbor/harbor/releases/download/v2.3.4/harbor-offline-installer-v2.3.4.tgz
|
上传到/root
解压
1
| tar -zxvf harbor-offline-installer-v2.3.4.tgz -C /usr/local/
|
1 2 3
| cd /usr/local/harbor cp harbor.yml.tmpl harbor.yml vim harbor.yml
|
修改为主机IP 端口我是使用7788,这个随意都行 注释https,因为没有证书

保存后 执行安装脚本


访问主页 IP:7788

登录进来新建一个项目

修改daemon.json,支持Docker仓库,并重启Docker
1 2 3 4
| { "registry-mirrors": ["https://pee6w651.mirror.aliyuncs.com"], "insecure-registries": ["192.168.117.141:7788"] }
|

重启docker 由于sonar容器没有做随dokcer启动而启动 所以需要启动一下sonar
1 2
| systemctl restart docker docker start $(docker ps -qa)
|
Jenkins容器使用宿主机Docker并编写构建脚本
设置宿主机docker.sock权限
1 2
| chown root:root /var/run/docker.sock chmod o+rw /var/run/docker.sock
|
挂载宿主机docker到容器
1
| vim /usr/local/jenkins/docker-compose.yml
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| version: "3.1" services: jenkins: image: jenkins/jenkins container_name: jenkins ports: - 8080:8080 - 50000:50000 volumes: - ./data/:/var/jenkins_home/ - /usr/bin/docker:/usr/bin/docker - /var/run/docker.sock:/var/run/docker.sock - /etc/docker/daemon.json:/etc/docker/daemon.json
|

重启Jenkins 容器
1 2
| cd /usr/local/jenkins/ docker-compose up -d
|

进入容器查看docker挂载情况,可以看到容器中也可以使用宿主机的docker
1 2
| docker exec -it jenkins bash docker ps
|

制作自定义镜像
回到Jenkins工程中 添加构建操作,执行shell
1 2 3 4 5 6
| cd /var/jenkins_home/workspace/${JOB_NAME}/docker mv ../target/*.jar ./ docker build -t ${JOB_NAME}:$tag . docker login -u admin -p Harbor12345 192.168.117.141:7788 docker tag ${JOB_NAME}:$tag 192.168.117.141:7788/devops/${JOB_NAME}:$tag docker push 192.168.117.141:7788/devops/${JOB_NAME}:$tag
|
1 2
| 注意这里必须要改镜像名字 否则推送不上Harboer仓库 登录密码 要写自己的账号密码,登录地址也要写仓库IP:端口 若是80端口也必须加上IP:80
|

编写Dockerfile
进入仓库目录创建dockerfile存放目录
1 2 3
| cd /root/devops-test/ mkdir docker vim docker/Dockerfile
|

1 2 3 4
| FROM java:openjdk-8u111 COPY *.jar /usr/local WORKDIR /usr/local CMD java -jar *.jar
|

修改标识
1
| vim src/main/java/com/example/testinit/controller/HelloWord.java
|

推送代码到仓库
1 2 3 4
| git add * git commit -m "create v1.0.1" git tag -a v1.0.1 -m "create v1.0.1" git push -u origin v1.0.1
|

再次提交v1.0.2版本
1
| vim src/main/java/com/example/testinit/controller/HelloWord.java
|

推送
1 2 3 4
| git add * git commit -m "create v1.0.2" git tag -a v1.0.1 -m "create v1.0.2" git push -u origin v1.0.2
|
可以看到gitlab已经有了两个新的分支

构建v1.0.1 不要构建v1.0.0 这个没有推动dockerfile

看输出台日志 表示已经推送到Harbor仓库


点击进来可以看到拉取命令及版本号

再次到Jenkins工程构建 v1.0.2版本

可以看到v1.0.2版本也推送进来了

sonar也有检测 因为代码是一样的 所以不会出现新的东西

编写启动脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| harbor_url=$1 harbor_project_name=$2 project_name=$3 tag=$4
imageName=$harbor_url/$harbor_project_name/$project_name:$tag
containerId=`docker ps -a | grep ${project_name} | awk '{print $1}'` if [ "$containerId" != "" ] ; then docker stop $containerId docker rm $containerId echo "Delete Container Success" fi
imageId=`docker images | grep ${project_name} | awk '{print $3}'`
if [ "$imageId" != "" ] ; then docker rmi -f $imageId echo "Delete Image Success" fi
docker login -u admin -p Harbor12345 $harbor_url
docker pull $imageName
docker run -d -p 9901:9901 --name $project_name $imageName
echo "Start Container Success" echo $project_name
|
1 2 3 4 5
| 参数解释 $1 为harbor仓库地址 $2 为harbor项目名 $3 jenkins工程名 $4 当前所用gitlab仓库中项目tag版本
|

全局可执行
1 2
| mv devops_start.sh /usr/bin/ chmod a+x /usr/bin/devops_start.sh
|
系统管理,插件管理
安装

配置服务器
获取Jenkins容器中的key
1 2 3 4
| docker exec -it jenkins bash ssh-keygen 一路回车 cat /var/jenkins_home/.ssh/id_rsa
|

复制key

发送秘钥到后端服务器
1 2 3
| ssh-copy-id root@192.168.117.141 yes 输出root密码
|

系统管理,系统配置 Publish over SSH

添加后端服务器

配置jenkins中devops-test工程
增加构建后操作 Send build artifacts over SSH

Exec command中填写
1
| devops_start.sh 192.168.117.141:7788 devops ${JOB_NAME} $tag
|

点击保存
构建工程 build v1.0.1
查看输出日志

访问IP:9901

Sonarqube 分析中也分析了一次

harbor中也重新推送了新的镜像

再次构建v1.0.2
访问IP:9901

清理名字标签为的镜像
完整的Jenkins 持续集成及持续发布就完成了