CICD-DevOps进阶-2
DevOps进阶
代码审计
介绍
SonarQube 是一个开源的代码质量管理平台,用于自动化检测代码中的质量问题和安全漏洞,帮助团队持续提升代码质量。
官方地址:https://www.sonarsource.com/products/sonarqube/downloads/
核心功能
静态代码分析
-
自动识别代码缺陷(如空指针异常)、安全漏洞(如SQL注入)和代码异味(不良设计),支持30+编程语言(Java、C#、Python等)。
-
集成PMD、FindBugs、Checkstyle等插件增强检测能力,提供深度规则定制。
多维质量指标
-
分析代码重复率、复杂度(圈复杂度)、注释覆盖率及单元测试覆盖率(需集成JaCoCo等工具)。
-
量化技术债务,生成修复优先级建议。
开发流程集成
-
无缝对接CI/CD工具(Jenkins、GitLab CI、GitHub Actions),提交代码后自动触发扫描。
-
通过IDE插件(SonarLint)实时反馈问题,支持开发阶段即时修复。
质量门禁(Quality Gate)
- 定义质量阈值(如漏洞数量上限),未达标代码自动阻断合并或部署。
部署
# 在jenkins服务器上拉取postgres数据库和代码审计sonarqube镜像
[root@Jenkins docker]# docker pull postgres
# 此版本为TLS长期稳定版
[root@Jenkins docker]# docker pull sonarqube:8.9.6-community# 创建代码审计容器脚本
[root@Jenkins docker]# mkdir /usr/local/docker/sonarqube-docker/
[root@Jenkins docker]# cd /usr/local/docker/sonarqube-docker/
[root@Jenkins sonarqube-docker]# cat > docker-compose.yaml << EOF
version: '3.1'
services:db:image: postgrescontainer_name: dbports:- 5432:5432networks:- sonarnetenvironment:POSTGRES_USER: sonarPOSTGRES_PASSWORD: sonarsonarquebe:image: sonarqube:8.9.6-communitycontainer_name: sonarqubedepends_on:- dbports:- 9000:9000networks:- sonarnetenvironment:SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonarSONAR_JDBC_USERNAME: sonarSONAR_JDBC_PASSWORD: sonar
networks:sonarnet:driver: bridge
EOF
[root@Jenkins sonarqube-docker]# docker-compose up -d# 查看容器
[root@Jenkins sonarqube-docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e95cf1837d4d sonarqube:8.9.6-community "bin/run.sh bin/sona…" About a minute ago Exited (0) About a minute ago sonarqube
edecbb87c868 postgres "docker-entrypoint.s…" 49 seconds ago Up 48 seconds 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp db
查看日志,查找失败原因
# 容器未运行查看日志
[root@Jenkins sonarqube-docker]# docker logs -f sonarqube
ERROR: [1] bootstrap checks failed. You must address the points described in the following [1] lines before starting Elasticsearch.
bootstrap check failure [1] of [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
ERROR: Elasticsearch did not exit normally - check the logs at /opt/sonarqube/logs/sonarqube.log
2025.08.11 03:53:00 INFO es[][o.e.n.Node] stopping ...
2025.08.11 03:53:00 INFO es[][o.e.n.Node] stopped
2025.08.11 03:53:00 INFO es[][o.e.n.Node] closing ...
2025.08.11 03:53:00 INFO es[][o.e.n.Node] closed
2025.08.11 03:53:00 WARN app[][o.s.a.p.AbstractManagedProcess] Process exited with exit value [es]: 78
2025.08.11 03:53:00 INFO app[][o.s.a.SchedulerImpl] Process[es] is stopped
2025.08.11 03:53:00 INFO app[][o.s.a.SchedulerImpl] SonarQube is stopped
解决问题:虚拟内存太小,max virtual memory areas vm.max_map_count [65530] is too low,increase to at least [262144],需要扩容
[root@Jenkins sonarqube-docker]# cat /etc/sysctl.conf
......
vm.max_map_count=262144
[root@Jenkins sonarqube-docker]# sysctl -p
vm.max_map_count = 262144
# 重新创建
[root@Jenkins sonarqube-docker]# docker-compose up -d
Starting db ... done
Starting sonarqube ... done
[root@Jenkins sonarqube-docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
814750ad3b62 sonarqube:8.9.6-community "bin/run.sh bin/sona…" 39 seconds ago Up 38 seconds 0.0.0.0:9000->9000/tcp, :::9000->9000/tcp sonarqube
edecbb87c868 postgres "docker-entrypoint.s…" 49 seconds ago Up 48 seconds 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp db
页面访问
登录
更新密码
登陆成功
安装中文插件
安装会报错
问题解决:
修正docker-compose.yaml文件
[root@Jenkins sonarqube-docker]# cat docker-compose.yaml
version: '3.1'
services:db:image: postgrescontainer_name: dbports:- 5432:5432networks:- sonarnetenvironment:POSTGRES_USER: sonarPOSTGRES_PASSWORD: sonarsonarquebe:image: sonarqube:8.9.6-communitycontainer_name: sonarqubedepends_on:- dbports:- 9000:9000volumes:- ./plugins/:/opt/sonarqube/extensions/plugins # 添加创建仓库数据卷networks:- sonarnetenvironment:SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonarSONAR_JDBC_USERNAME: sonarSONAR_JDBC_PASSWORD: sonar
networks:sonarnet:driver: bridge# 重启服务
[root@Jenkins sonarqube-docker]# docker-compose stop
Stopping sonarqube ... done
Stopping db ... done
[root@Jenkins sonarqube-docker]# docker-compose up -d
Starting db ... done
Recreating sonarqube ... done
[root@Jenkins sonarqube-docker]# ls
docker-compose.yaml plugins
# 将本地插件sonar-l10n-zh-plugin-8.9.jar复制到plugins目录中,再次重启
[root@Jenkins sonarqube-docker]# cp sonar-l10n-zh-plugin-8.9.jar plugins/
[root@Jenkins sonarqube-docker]# docker-compose restart
Restarting sonarqube ... done
Restarting db ... done
页面显示为中文
代码测试
回到Windows系统的idea上
sonarqube会支持两种方式测试代码:
maven方式
1:maven方式,sonarqube对maven有支持,可以使用maven命令对代码测试。
修改maven目录下的settings.xml文件
指定位置插入如下内容:sonarqube的用户名、密码和Jenkins主机节点
<profile><id>sonar</id><activation><activeByDefault>true</activeByDefault></activation><properties><sonar.login>admin</sonar.login><sonar.password>Gzq20000308.</sonar.password> # sonarqube密码<sonar.host.url>http://10.1.8.102:9000</sonar.host.url> # jenkins主机节点</properties>
</profile>
设置环境变量
重启idea,终端执行命令
执行代码
版本报错
原因:sonar-maven-plugin:4.0.0.4121默认支持jdk11,而项目中使用的是jdk8,导致版本出错
解决问题:
可以采用下载对应的sonar-maven-plugin:3.11.0.3922版本来解决
在pom.xml中插入以下内容:
<plugin><groupId>org.sonarsource.scanner.maven</groupId><artifactId>sonar-maven-plugin</artifactId><version>3.11.0.3922</version>
</plugin>
重启执行mvn sonar:sonar,进行加载
打开sonarqube网页,完成项目代码审计
查看检测结果
sonar-scanner方式
官方插件下载地址:https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/sonarscanner/
# 把本地压缩包sonar-scanner-cli-4.6.0.2311-linux.zip解压到Jenkins的data目录中
[root@Jenkins ~]# unzip sonar-scanner-cli-4.6.0.2311-linux.zip
[root@Jenkins ~]# mv sonar-scanner-4.6.0.2311-linux/ /usr/local/docker/jenkins-docker/data/sonar-scanner# 修改配置
[root@Jenkins ~]# cd /usr/local/docker/jenkins-docker/data/sonar-scanner/conf
[root@Jenkins conf]# cat sonar-scanner.properties
#Configure here general information about the environment, such as SonarQube server connection details for example
#No information about specific project should appear here#----- Default SonarQube server
sonar.host.url=http://10.1.8.102:9000 # 去掉注释,改为jenkins地址#----- Default source code encoding
sonar.sourceEncoding=UTF-8 # 去掉注释# 进行项目代码测试
[root@Jenkins conf]# cd /usr/local/docker/jenkins-docker/data/workspace/mytest
[root@Jenkins mytest]# /usr/local/docker/jenkins-docker/data/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=linux-test
INFO: Scanner configuration file: /usr/local/docker/jenkins-docker/data/sonar-scanner/conf/sonar-scanner.properties
INFO: Project root configuration file: NONE
INFO: SonarScanner 4.6.0.2311
INFO: Java 11.0.3 AdoptOpenJDK (64-bit)
INFO: Linux 3.10.0-693.el7.x86_64 amd64
INFO: User cache: /root/.sonar/cache
INFO: Scanner configuration file: /usr/local/docker/jenkins-docker/data/sonar-scanner/conf/sonar-scanner.properties
INFO: Project root configuration file: NONE
INFO: Analyzing on SonarQube server 8.9.6
INFO: Default locale: "zh_CN", source code encoding: "UTF-8"
INFO: Load global settings
INFO: ------------------------------------------------------------------------
INFO: EXECUTION FAILURE
INFO: ------------------------------------------------------------------------
INFO: Total time: 1.251s
INFO: Final Memory: 4M/17M
INFO: ------------------------------------------------------------------------
ERROR: Error during SonarScanner execution
ERROR: Not authorized. Analyzing this project requires authentication. Please provide a user token in sonar.login or other credentials in sonar.login and sonar.password.
ERROR:
ERROR: Re-run SonarScanner using the -X switch to enable full debug logging.
错误显示为未授权,需要进行token令牌身份已验证
sonar页面右上角-用户-我的账号
输入admin生成token
添加参数,再次执行
# 添加token
[root@Jenkins mytest]# /usr/local/docker/jenkins-docker/data/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=linux-test -Dsonar.login=9ed21fcf9e783cd83063a99015b24fbf3b9a7003 -Dsonar.projectKey=linux-test
......
ERROR: Error during SonarScanner execution
org.sonar.java.AnalysisException: Your project contains .java files, please provide compiled classes with sonar.java.binaries property, or exclude them from the analysis with sonar.exclusions property.# 继续添加参数,重新执行,指定java目标库
[root@Jenkins mytest]# /usr/local/docker/jenkins-docker/data/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=linux-test -Dsonar.login=9ed21fcf9e783cd83063a99015b24fbf3b9a7003 -Dsonar.projectKey=linux-test -Dsonar.java.binaries=./target/
回到sonarqube网页查看
代码审计整合Jenkins
整合sonarqube实现自动化代码审计
使用插件导入sonar.hpi
jenkins页面-系统管理-插件管理-
查看已安装插件
系统管理-系统配置-sonarQube servers
返回系统配置
添加凭据
调用sonar-scanner工具
系统管理-全局工具配置
添加容器内部路径
jenkins首页项目中配置
构建位置进行添加构建步骤
代码如下
sonar.projectname=${JOB_NAME}
sonar.projectKey=${JOB_NAME}
sonar.source=./
sonar.java.binaries=target
进行构建
解决问题:因为之前在Jenkins服务器上使用命令进行了构建,产生过隐藏文件.scannerwork夹需要删除
[root@Jenkins mytest]# ls -a
. demo-web.iml .git .gitignore .idea .scannerwork target
.. docker .gitattributes HELP.md pom.xml src
[root@Jenkins mytest]# rm .scannerwork/ -rf
再次构建
构建完成,过程中调用了sonarqube
查看sonarqube网页,观察结果
Jenkins整合harbor
Harbor镜像仓库
部署
# 将本地harbor压缩包上传至jenkins服务器,并解压
[root@Jenkins ~]# tar -xf harbor-offline-installer-v2.8.2.tgz -C /usr/local/
[root@Jenkins ~]# cd /usr/local/harbor/
[root@Jenkins harbor]# cp -p harbor.yml.tmpl harbor.yml
# 修改配置
[root@Jenkins harbor]# cat harbor.yml
......
hostname: 10.1.8.102 # 5行
......
#https:
# # https port for harbor, default is 443 # 13行
# port: 443
# # The path of cert and key files for nginx
# certificate: /your/certificate/path
# private_key: /your/private/key/path
......
harbor_admin_password: Gzq20000308. # 34行
......
# 安装脚本
[root@Jenkins harbor]# ./install.sh
页面访问harbor,用户:admin
新建项目
设置项目公开
添加仓库地址
# 修改daemon.json配置文件添加仓库地址
[root@Jenkins harbor]# cat /etc/docker/daemon.json
{
"insecure-registries":["10.1.8.102:80"], # 添加仓库地址及端口
"registry-mirrors": [
"https://09def58152000fc00ff0c00057bad7e0.mirror.swr.myhuaweicloud.com",
"https://do.nark.eu.org",
"https://dc.j8.work",
"https://docker.m.daocloud.io",
"https://dockerproxy.com",
"https://docker.mirrors.ustc.edu.cn",
"https://docker.nju.edu.cn",
"https://registry.docker-cn.com",
"https://hub-mirror.c.163.com",
"https://hub.uuuadc.top",
"https://docker.anyhub.us.kg",
"https://dockerhub.jobcher.com",
"https://dockerhub.icu",
"https://docker.ckyl.me",
"https://docker.awsl9527.cn",
"https://mirror.baidubce.com",
"https://docker.1panel.live"
]
}# 重启所有需要运行 docker 的服务,以识别 harbor 仓库
# 重启 docker
[root@Jenkins harbor]# systemctl restart docker
# 重启 harbor
[root@Jenkins harbor]# docker-compose restart
Restarting harbor-jobservice ... done
Restarting nginx ... done
Restarting harbor-core ... done
Restarting harbor-db ... done
Restarting harbor-portal ... done
Restarting registryctl ... done
Restarting registry ... done
Restarting redis ... done
Restarting harbor-log ... done
# 重启 jenkins
[root@Jenkins harbor]# cd /usr/local/docker/jenkins-docker/
[root@Jenkins jenkins-docker]# docker-compose restart
Restarting jenkins ... done
[root@Jenkins jenkins-docker]# cd /usr/local/docker/sonarqube-docker/
[root@Jenkins sonarqube-docker]# docker-compose restart
Restarting sonarqube ... done
Restarting db ... done
推送镜像
Jenkins服务器本地登录harbor,并测试镜像推送
# 本地登录harbor
[root@Jenkins ~]# docker login -u admin -p Gzq20000308. 10.1.8.102:80
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded# 拉取镜像
[root@Jenkins ~]# docker pull nginx
# 将镜像打上tag标签
# 镜像命名规范:仓库IP地址/项目名称/镜像名称:版本号
[root@Jenkins ~]# docker tag nginx:latest 10.1.8.102:80/repo/nginx:test
# 推送镜像到 harbor
[root@Jenkins ~]# docker push 10.1.8.102:80/repo/nginx:test
到 harbor 仓库查看镜像是否推送成功
拉取镜像
本地测试拉取镜像
# 删除原有镜像
[root@Jenkins ~]# docker rmi 10.1.8.102:80/repo/nginx:test
[root@Jenkins ~]# docker rmi nginx:latest
# 拉取镜像
[root@Jenkins ~]# docker pull 10.1.8.102:80/repo/nginx:test
[root@Jenkins ~]# docker images 10.1.8.102:80/repo/nginx
REPOSITORY TAG IMAGE ID CREATED SIZE
10.1.8.102:80/repo/nginx test 2cd1d97f893f 4 weeks ago 192MB
Jenkins服务使用Docker
Jenkins需要把镜像制作并推送到harbor中,就需要具备docker环境让Jenkins容器使用宿主机中docker环境
# 修改docker。sock权限
[root@Jenkins ~]# ll /var/run/docker.sock
srw-rw---- 1 root docker 0 8月 8 10:47 /var/run/docker.sock
[root@Jenkins ~]# chown root:root /var/run/docker.sock
[root@Jenkins ~]# chmod o+rw /var/run/docker.sock
[root@Jenkins ~]# ll /var/run/docker.sock
srw-rw-rw- 1 root root 0 8月 8 10:47 /var/run/docker.sock# 修改脚本配置文件
version: "3.1"
services:jenkins:image: jenkins/jenkins:2.346.3-lts-jdk8container_name: jenkinsports: # 映射端口- 8080:8080- 50000:50000volumes: # 映射目录- ./data/:/var/jenkins_home/- /var/run/docker.sock:/var/run/docker.sock # 添加- /usr/bin/docker:/usr/bin/docker # 添加- /etc/docker/daemon.json:/etc/docker/daemon.json # 添加
# 启动服务
[root@Jenkins jenkins-docker]# docker-compose up -d
# 进入容器验证docker命令
[root@Jenkins jenkins-docker]# docker exec -it jenkins bash
jenkins@392ae884a4ea:/$ docker version
Client: Docker Engine - CommunityVersion: 26.1.4API version: 1.45Go version: go1.21.11Git commit: 5650f9bBuilt: Wed Jun 5 11:32:04 2024OS/Arch: linux/amd64Context: defaultServer: Docker Engine - CommunityEngine:Version: 26.1.4API version: 1.45 (minimum version 1.24)Go version: go1.21.11Git commit: de5c9cfBuilt: Wed Jun 5 11:31:02 2024OS/Arch: linux/amd64Experimental: falsecontainerd:Version: 1.6.33GitCommit: d2d58213f83a351ca8f528a95fbd145f5654e957runc:Version: 1.1.12GitCommit: v1.1.12-0-g51d5e94docker-init:Version: 0.19.0GitCommit: de40ad0
Jenkins服务构建镜像推送harbor仓库
到Windows系统的idea中,删除docker-compose文件
修改一下内容3.0重新提交
添加3.0标签
本地构建镜像
jenkins页面-项目-配置-构建后操作
mv target/*.jar docker/
docker build -t mytest:$tag docker/
选择对应标签进行构建
在Jenkins服务器这种查看镜像
[root@Jenkins workspace]# docker images mytest
REPOSITORY TAG IMAGE ID CREATED SIZE
mytest v3.0 1561ce81f5f5 About a minute ago 543MB
推送至harbor
jenkins-项目-配置-构建
docker login -u admin -p Gzq20000308. 10.1.8.102:80
docker tag mytest:$tag 10.1.8.102:80/repo/mytest:$tag
docker push 10.1.8.102:80/repo/mytest:$tag
再次进行构建3.0项目
harbor仓库查看存储的镜像
镜像部署到目标web服务器
告知目标服务器拉取哪个镜像。告知内容(harbor地址;harbor仓库名;镜像名;镜像版本;容器运行端口号)
判断当前服务器是否正在运行该容器,如果正在运行则需要删除。
如果目标服务器已经存在当前镜像,则需要删除该镜像。
目标服务器拉取harbor上的镜像。
将拉取的镜像运行为容器
在jenkins编写脚本
[root@Jenkins ~]# cat /usr/local/docker/jenkins-docker/data/workspace/mytest/deploy.sh
#!/bin/bash
harbor_ip=$1 # harbor地址
harbor_repo=$2 # harbor仓库名
project=$3 # 项目名
version=$4 # 镜像版本
container_port=$5 # 容器暴露端口
host_port=$6 # 主机暴露端口imageName=$harbor_ip/$harbor_repo/$project:$version # 镜像名
echo $imageName# 查找项目容器id
container_id=`docker ps -a | grep ${project} | awk '{print $1}'`
echo $container_id
# 如果项目容器id不为空,则停止同ID容器并删除
if [ "$container_id" != "" ]
thendocker stop $container_iddocker rm $container_id
fi# 查找项目镜像标签tag
tag=`docker images | grep ${project} | awk '{print $2}'`
echo $tag
# 如果拉取的项目镜像标签已存在,则删除镜像
if [[ "$tag" =~ "$version" ]]
thendocker rmi $imageName
fi# 登录harbor仓库
cp /lib/systemd/system/docker.service /lib/systemd/system/docker.service.bak
sed -i 's#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock#ExecStart=/usr/bin/dockerd -H fd:// --insecure-registry 10.1.8.102 --containerd=/run/containerd/containerd.sock#g' /lib/systemd/system/docker.service
# 重启docker,并登录仓库
systemctl daemon-reload && systemctl restart docker && docker login -u admin -p Gzq20000308. $harbor_ip# 拉取镜像
docker pull $imageName# 运行容器
docker run -d -p $host_port:$container_port --name $project $imageName echo "SUCCESS"# 将脚本放到mytest项目目录下,等待发送给目标服务器
[root@Jenkins ~]# mv deploy.sh /usr/local/docker/jenkins-docker/data/workspace/mytest
jenkins页面-项目-配置-General
构建后操作

mv /usr/local/test/deploy.sh /usr/bin/
chmod +x /usr/bin/deploy.sh
deploy.sh 10.1.8.102 repo ${JOB_NAME} $tag $container_port $host_port
进行构建
到目标服务器web中查看镜像
[root@Web ~]# docker images | grep 10.1.8.102
10.1.8.102/repo/mytest v3.0 19d59e0f6f8a 14 minutes ago 543MB
页面访问验证