如何在CircleCI上启动SonarQube Server并运行sonar-scanner
CircleCI 集成 SonarQube 扫描报错解决方案
问题根因
报错连接localhost:9000失败由三个直接原因导致:
- 现有配置仅启动了OpenJDK运行环境,没有部署可访问的SonarQube Server实例
- Sonar Scanner执行命令存在语法错误:
-Dsonar.projectKey=projectKey行末尾缺少续行反斜杠,后续配置的服务地址、认证信息等参数全部未生效,Scanner自动回退使用默认的本地9000端口作为服务地址 - 额外问题:使用的4.2.0版本Sonar Scanner发布时间较早,和当前主流版本SonarQube存在兼容性问题
可选方案
方案1:对接独立部署的SonarQube实例(生产环境推荐)
该方案稳定性最高,不会因为CI任务销毁丢失历史扫描数据,是企业级使用的标准做法:
- 提前部署可被CircleCI环境网络访问的SonarQube服务(自托管实例或SonarCloud均可)
- 在CircleCI对应项目的
lineclass上下文里正确配置三个环境变量:SONAR_SERVER:SonarQube服务的访问地址,例如https://sonar.your-company.comSONAR_TOKEN:SonarQube后台生成的、拥有目标项目扫描权限的访问令牌SONAR_SOURCES:待扫描的代码目录路径,例如src
- 使用修正后的配置替换原有
config.yml,修复语法错误、升级Scanner版本:
version: 2.1 executors: scanner: docker: - image: openjdk:11 resource_class: medium+ # 给足Scanner运行内存 commands: check-code-quality: description: Check Code Quality parameters: sonar_server_url: type: string description: "URL of your SonarQube server. e.g.: http://my.sonarqube.server:9000" default: "$SONAR_SERVER" sonar_login: description: "Authentication key (sonar.login parameter) to access SonarQube and perform analysis" type: string default: "$SONAR_TOKEN" sonar_sources: description: "Where the files are located?" type: string default: "$SONAR_SOURCES" steps: - run: name: Install Sonarqube scanner command: | # 升级到兼容新版SonarQube的稳定版Scanner wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.8.0.2856.zip unzip -q sonar-scanner-cli-4.8.0.2856.zip chmod +x ./sonar-scanner-4.8.0.2856/bin/sonar-scanner - run: name: Run Sonarscanner command: | export SONAR_SCANNER_OPTS="-Xmx2048m" ./sonar-scanner-4.8.0.2856/bin/sonar-scanner \ -Dsonar.projectKey=projectKey \ -Dsonar.host.url=<< parameters.sonar_server_url >> \ -Dsonar.sources=<< parameters.sonar_sources >> \ -Dsonar.login=<< parameters.sonar_login >> jobs: check-code-job: executor: scanner steps: - checkout # 必须先拉取代码,不然Scanner找不到源码 - check-code-quality workflows: check-code-quality-flow: jobs: - check-code-job: context: lineclass
方案2:在CircleCI任务内临时启动SonarQube实例(仅适合测试场景)
如果仅做功能测试、不需要留存历史扫描数据,可以直接把SonarQube作为CI任务的附属服务容器启动,注意该模式下任务结束后所有扫描数据会被销毁,不适合生产使用:
- 修改executor配置,添加SonarQube服务容器,选择内存不小于4G的资源类(SonarQube启动最低要求2G可用内存)
- 添加服务探活步骤,等SonarQube完全启动完成后再运行扫描(服务容器启动后需要30-60秒初始化,直接运行Scanner依然会报连接错误)
- 临时实例默认管理员账号为
admin/admin,可通过接口自动生成临时扫描令牌
对应配置参考:
version: 2.1 executors: scanner-with-sonar: docker: - image: openjdk:11 - image: sonarqube:9.9-community # 长期支持版SonarQube name: sonarqube resource_class: large # 分配4G内存保证SonarQube正常启动 commands: check-code-quality-temp: steps: - run: name: Install Sonarqube scanner command: | wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.8.0.2856.zip unzip -q sonar-scanner-cli-4.8.0.2856.zip chmod +x ./sonar-scanner-4.8.0.2856/bin/sonar-scanner - run: name: Wait for SonarQube to be ready command: | for i in {1..30}; do if curl -s http://localhost:9000/api/system/status | grep -q '"status":"UP"'; then echo "SonarQube is ready" exit 0 fi echo "Waiting for SonarQube to start..." sleep 2 done echo "SonarQube failed to start within timeout" exit 1 - run: name: Generate temp scan token and run scan command: | export SONAR_SCANNER_OPTS="-Xmx2048m" # 用默认管理员账号生成临时token TOKEN=$(curl -s -X POST -u admin:admin http://localhost:9000/api/user_tokens/generate?name=ci-temp-token | grep -o '"token":"[^"]*"' | cut -d'"' -f4) ./sonar-scanner-4.8.0.2856/bin/sonar-scanner \ -Dsonar.projectKey=test-project \ -Dsonar.host.url=http://localhost:9000 \ -Dsonar.sources=src \ -Dsonar.login=$TOKEN \ -Dsonar.projectBaseDir=$(pwd) jobs: check-code-job-temp: executor: scanner-with-sonar steps: - checkout - check-code-quality-temp workflows: test-scan: jobs: - check-code-job-temp
注意事项
- 临时启动SonarQube的模式下,第一次运行可能因为服务初始化慢触发超时,适当调大探活等待时长即可
- 不要在CI流程里用docker-in-docker的方式启动SonarQube,稳定性远低于原生附属服务容器模式
- 生产环境强烈建议使用独立部署的SonarQube实例,避免CI资源浪费和扫描数据丢失
内容的提问来源于stack exchange,提问作者Loc Truong
相关产品推荐
相关产品推荐

