SonarQube 与 GitLab CI/CD 集成心路历程

195 阅读9分钟

SonarQube 与 GitLab CI/CD 集成心路历程

本文档记录了从零开始配置 SonarQube 代码扫描并与 GitLab CI/CD 集成的完整过程,包括所有遇到的问题、解决方案和经验总结。

创建时间: 2025-12-02
项目: YourProject
目标: 实现代码质量自动扫描,集成到 GitLab CI/CD 流程


📋 目录


项目背景

需求

  1. 部署 SonarQube 用于代码质量扫描
  2. 集成到 GitLab CI/CD 流程
  3. 实现代码提交自动触发扫描
  4. 初期阶段允许 CI 失败时不阻止代码合并

技术栈

  • SonarQube: 9.9-community
  • GitLab: 自建服务器 (示例: 192.168.1.100:8002)
  • Docker: 容器化部署
  • 网络: cloud-desktop_private-repos (示例: 10.0.0.x)

第一阶段:SonarQube Docker 部署

1.1 参考 MCP 配置风格

参考配置:

services:
  confluence-service:
    image: ghcr.io/sooperset/mcp-atlassian:latest
    container_name: confluence-service
    ports:
      - "3009:9000"
    environment:
      - CONFLUENCE_URL=http://192.168.1.101:8090
      - CONFLUENCE_USERNAME=readonly
      - CONFLUENCE_API_TOKEN=your-api-token-here
    command: ["--transport", "streamable-http", "--port", "9000"]
    restart: unless-stopped
    networks:
      cloud-desktop_private-repos:
        ipv4_address: 10.0.0.13

关键点:

  • 没有 version 字段(新版 Docker Compose 不需要)
  • 使用固定 IP 地址
  • 端口映射格式:"3011:9000"
  • 网络使用 cloud-desktop_private-repos
  • restart: unless-stopped

1.2 初始配置

位置: docker/sonarqube/docker-compose.yml

services:
  sonarqube-service:
    image: sonarqube:9.9-community
    container_name: sonarqube-service
    ports:
      - "3011:9000"
    environment:
      - TZ=Asia/Shanghai
      - SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true
    volumes:
      - /home/code/sonarqube/data:/opt/sonarqube/data
      - /home/code/sonarqube/logs:/opt/sonarqube/logs
      - /home/code/sonarqube/temp:/opt/sonarqube/temp
      - /home/code/sonarqube/extensions:/opt/sonarqube/extensions
    restart: unless-stopped
    networks:
      cloud-desktop_private-repos:
        ipv4_address: 10.0.0.15

networks:
  cloud-desktop_private-repos:
    external: true

端口选择:

  • Confluence MCP: 3009
  • Jira MCP: 3010
  • SonarQube: 3011

第二阶段:GitLab CI/CD 配置

2.1 初始配置问题

问题 1:artifacts 配置语法错误

# ❌ 错误配置
artifacts:
  when: on_failure
  paths:
    - ruoyi-ui/
  reports:  # 空的 reports 导致语法错误
    # 注释内容
    expire_in: 1 week

错误信息:

jobs:frontend-lint:artifacts config contains unknown keys: reports

解决方案:

# ✅ 正确配置
artifacts:
  when: on_failure
  paths:
    - ruoyi-ui/
  # 如果 ESLint 支持 JSON 报告格式,可以在这里配置 reports
  # reports:
  #   codequality: ruoyi-ui/eslint-report.json
  expire_in: 1 week

问题 2:dependencies 配置错误

# ❌ 错误配置
quality-gate:
  stage: lint  # 与 backend-sonar 在同一 stage
  dependencies:
    - backend-sonar  # 不能依赖同一 stage 的 job

错误信息:

quality-gate job: dependency backend-sonar is not defined in prior stages

解决方案:

# ✅ 正确配置
stages:
  - lint
  - quality-check  # 新增 stage

quality-gate:
  stage: quality-check  # 移到新 stage
  dependencies:
    - backend-sonar  # 现在可以依赖 lint stage 的 job

问题 3:分支配置缺失

错误信息:

No stages / jobs for this pipeline.

原因: .gitlab-ci.yml 中的 only 配置只包含 maindevelopmerge_requests,不包含当前分支(如 feature/your-branch-name)。

解决方案:

# ✅ 在所有 job 的 only 中添加分支
only:
  - merge_requests
  - main
  - develop
  - feature/your-branch-name  # 添加当前分支

2.2 最终 GitLab CI/CD 配置

文件: .gitlab-ci.yml

关键配置:

  • allow_failure: true - 允许失败时不阻止合并
  • 使用环境变量:SONAR_HOST_URLSONAR_TOKEN
  • 分两个 stage:lintquality-check

第三阶段:GitLab Runner 安装

3.1 安装过程

执行目录: /home/ubuntu(用户主目录)

步骤 1:添加软件源

cd ~
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash

遇到的问题:

  • 网络慢:ping 延迟 280-290ms
  • 软件源添加需要 2-5 分钟
  • 解决方案:耐心等待,或使用手动下载安装包

步骤 2:安装 GitLab Runner

sudo apt-get update
sudo apt-get install -y gitlab-runner

遇到的问题:依赖问题

# ❌ 错误:直接使用 dpkg 安装
sudo dpkg -i gitlab-runner_amd64.deb
# 错误:gitlab-runner depends on gitlab-runner-helper-images (= 18.6.3-1)

# ❌ 错误:使用 apt-get install -f
sudo apt-get install -f
# 结果:把 gitlab-runner 卸载了!

解决方案:

# ✅ 正确方法:通过软件源安装(自动处理依赖)
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt-get update
sudo apt-get install -y gitlab-runner

步骤 3:注册 Runner

sudo gitlab-runner register \
  --non-interactive \
  --url "http://your-gitlab-server:8002/" \
  --registration-token "YOUR_GITLAB_REGISTRATION_TOKEN" \
  --executor "docker" \
  --docker-image "maven:3.9-eclipse-temurin-21" \
  --description "YourProject-Dedicated-Runner" \
  --tag-list "docker" \
  --docker-privileged=false \
  --docker-volumes "/var/run/docker.sock:/var/run/docker.sock"

注意:

  • --url: 替换为您的 GitLab 服务器地址
  • --registration-token: 在 GitLab 项目的 Settings → CI/CD → Runners 中获取

成功输出:

Registering runner... succeeded
Runner registered successfully.
Configuration was saved in "/etc/gitlab-runner/config.toml"

步骤 4:配置 Docker 权限

sudo usermod -aG docker gitlab-runner
groups gitlab-runner

安全性说明:

  • ✅ 只影响 gitlab-runner 用户
  • ✅ 不影响其他用户和服务
  • ✅ 不影响现有容器
  • ✅ 这是 GitLab Runner 使用 Docker executor 的标准配置

步骤 5:启动 Runner

sudo gitlab-runner start
sudo gitlab-runner status

遇到的问题与解决方案

问题 1:SonarQube 权限问题

症状:

Permission denied
/opt/sonarqube/temp/sharedmemory (Permission denied)

原因:

  • 目录所有者不是 999:999(SonarQube 容器使用的 UID/GID)
  • 可能是其他用户或组(如 user:group
  • SonarQube 容器使用 UID 999 运行

尝试的解决方案:

  1. sudo chown -R 999:999 - 命令执行但权限未改变(可能是 ACL 或其他问题)
  2. user: "0:0" - Elasticsearch 禁止以 root 运行
  3. 使用 Docker 卷 - 最终解决方案

最终解决方案:

volumes:
  sonarqube_data:/opt/sonarqube/data
  sonarqube_logs:/opt/sonarqube/logs
  sonarqube_temp:/opt/sonarqube/temp
  sonarqube_extensions:/opt/sonarqube/extensions

volumes:
  sonarqube_data:
  sonarqube_logs:
  sonarqube_temp:
  sonarqube_extensions:

经验: Docker 卷自动管理权限,比手动管理宿主机目录权限更可靠。

问题 2:Elasticsearch 不能以 root 运行

症状:

can not run elasticsearch as root

原因: Elasticsearch 安全限制,禁止以 root 用户运行。

解决方案: 删除 user: "0:0" 配置,使用容器默认用户(UID 999)。

问题 3:网络问题(境外源慢)

症状:

  • 添加软件源卡住很久
  • ping 延迟 280-290ms

解决方案:

  • 耐心等待(2-5 分钟)
  • 或使用手动下载安装包(但依赖包下载遇到 403)

经验: 国内访问 GitLab 官方源较慢,需要耐心等待。

问题 4:依赖包问题

症状:

gitlab-runner depends on gitlab-runner-helper-images (= 18.6.3-1) but it is not installable

原因:

  • 直接使用 dpkg -i 不处理依赖
  • 手动下载依赖包遇到 403 Forbidden

解决方案:

  • 使用 apt-get install 通过软件源安装,自动处理依赖

经验: 优先使用包管理器安装,而不是直接安装 deb 包。

问题 5:Pipeline 显示 "等待中"

症状:

  • Pipeline 创建后一直显示 "等待中"
  • 没有 Runner 执行任务

可能原因:

  1. Runner 服务未启动
  2. Runner 未正确注册
  3. Runner tags 不匹配
  4. Runner 被暂停

检查方法:

# 服务器上检查
sudo gitlab-runner status
sudo gitlab-runner list

# GitLab 页面检查
Settings → CI/CD → Runners

最终配置

SonarQube Docker Compose

文件: docker/sonarqube/docker-compose.yml

services:
  sonarqube-service:
    image: sonarqube:9.9-community
    container_name: sonarqube-service
    ports:
      - "3011:9000"
    environment:
      - TZ=Asia/Shanghai
      - SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true
    volumes:
      - sonarqube_data:/opt/sonarqube/data
      - sonarqube_logs:/opt/sonarqube/logs
      - sonarqube_temp:/opt/sonarqube/temp
      - sonarqube_extensions:/opt/sonarqube/extensions
    restart: unless-stopped
    networks:
      cloud-desktop_private-repos:
        ipv4_address: 10.0.0.15

volumes:
  sonarqube_data:
  sonarqube_logs:
  sonarqube_temp:
  sonarqube_extensions:

networks:
  cloud-desktop_private-repos:
    external: true

GitLab CI/CD 配置

文件: .gitlab-ci.yml

关键点:

  • 两个 stage:lintquality-check
  • allow_failure: true - 允许失败时不阻止合并
  • 所有 job 都包含需要运行的分支(如 feature/your-branch-name

GitLab 变量配置

位置: Settings → CI/CD → Variables

变量名说明
SONAR_HOST_URLhttp://your-sonarqube-server:3011SonarQube 服务器地址
SONAR_TOKENsqu_xxxxx...SonarQube 访问令牌(在 SonarQube 中生成)

GitLab Runner 配置

Runner 信息:

  • 名称:YourProject-Dedicated-Runner
  • Executor:docker
  • Tags:docker
  • 默认镜像:maven:3.9-eclipse-temurin-21
  • 状态:online

经验总结

1. Docker 卷 vs 宿主机目录

推荐: 使用 Docker 卷

  • ✅ 自动管理权限
  • ✅ 更可靠
  • ✅ 避免权限问题

不推荐: 直接挂载宿主机目录(除非有特殊需求)

  • ❌ 需要手动管理权限
  • ❌ 容易出问题

2. GitLab CI/CD 配置

关键点:

  • only 配置要包含所有需要运行的分支
  • dependencies 只能依赖前面 stage 的 job
  • artifacts.reports 不能为空

3. GitLab Runner 安装

推荐流程:

  1. 通过软件源安装(自动处理依赖)
  2. 注册 Runner
  3. 配置 Docker 权限
  4. 启动服务

避免:

  • ❌ 直接使用 dpkg -i 安装(不处理依赖)
  • ❌ 手动下载依赖包(可能遇到 403)

4. 网络问题处理

国内访问 GitLab 官方源:

  • 延迟较高(280-290ms)
  • 需要耐心等待(2-5 分钟)
  • 建议在网络较好的时段操作

5. 安全性考虑

Docker 权限配置:

  • sudo usermod -aG docker gitlab-runner 是安全的
  • 只影响 gitlab-runner 用户
  • 不影响其他服务
  • 这是标准配置

6. 配置验证

每个阶段都要验证:

  1. SonarQube:访问 http://your-sonarqube-server:3011 确认运行
  2. GitLab CI:检查 YAML 语法(CI Lint)
  3. GitLab Runner:检查服务状态和在线状态

配置检查清单

SonarQube 部署

  • Docker Compose 配置完成
  • 使用 Docker 卷(解决权限问题)
  • 网络配置正确(cloud-desktop_private-repos)
  • 固定 IP 配置(示例: 10.0.0.15)
  • 端口映射正确(3011:9000)
  • SonarQube 可以访问
  • 中文语言包已安装

GitLab CI/CD 配置

  • .gitlab-ci.yml 语法正确
  • Stage 配置正确(lint, quality-check)
  • Job 依赖关系正确
  • 分支配置完整(包含所有需要运行的分支)
  • allow_failure: true 配置
  • 环境变量已配置(SONAR_HOST_URL, SONAR_TOKEN)

GitLab Runner 配置

  • Runner 已安装(18.6.3)
  • Runner 已注册
  • Docker 权限已配置
  • Runner 服务已启动
  • GitLab 页面显示 online
  • Tags 配置正确(docker)

集成测试

  • Pipeline 可以创建
  • Runner 可以执行任务
  • SonarQube 扫描可以运行
  • 结果可以推送到 SonarQube

后续优化建议

1. 性能优化

  • 配置 Runner 并发数(concurrent = 4
  • 优化 Docker 镜像拉取策略(pull_policy = ["if-not-present"]
  • 配置缓存策略

2. 安全加固

  • 定期更新 GitLab Runner
  • 配置 Runner 网络隔离
  • 限制 Runner 权限范围

3. 监控告警

  • 监控 Runner 状态
  • 监控 Pipeline 执行情况
  • 监控 SonarQube 服务状态

4. 文档完善

  • 更新部署文档
  • 记录常见问题
  • 编写故障排查指南

参考文档


更新记录

  • 2025-12-02: 初始版本,完成 SonarQube 与 GitLab CI/CD 集成

文档维护者: YourTeam
最后更新: 2025-12-02


⚠️ 安全说明

本文档中的所有敏感信息已进行脱敏处理:

  • IP 地址:已替换为示例 IP(如 192.168.1.x10.0.0.x
  • GitLab 注册令牌:已替换为 YOUR_GITLAB_REGISTRATION_TOKEN
  • API Token:已替换为示例格式(如 your-api-token-here
  • 分支名称:已替换为示例分支名(如 feature/your-branch-name
  • 项目名称:已替换为 YourProject
  • 服务器地址:已替换为 your-gitlab-serveryour-sonarqube-server

使用本文档时,请替换所有示例值为您的实际配置!