参考资料
前言
在 AI 编码工具(Cursor、OpenCode 等)日益普及的今天,如何保证 AI 生成代码的质量,成为一个新的挑战。
SonarQube 作为业界领先的代码质量平台,提供了静态代码分析、Bug 检测、安全漏洞扫描、代码异味识别等功能。而 MCP(Model Context Protocol)则让 AI 工具能直接调用外部服务。两者的结合,让 AI 编码中的质量检视变得自动化。
Docker Compose 部署 SonarQube
SonarQube 依赖 PostgreSQL 数据库,完整的部署方案如下:
目录结构
sonarqube/
├── docker-compose.yml
├── data/
├── logs/
├── extensions/
└── conf/docker-compose.yml
networks:
dev-net:
external: true
services:
SonarQube:
image: sonarqube:latest
container_name: SonarQube
volumes:
- ./data:/opt/sonarqube/data
- ./logs:/opt/sonarqube/logs
- ./extensions:/opt/sonarqube/extensions
- ./conf:/opt/sonarqube/conf
environment:
SONAR_JDBC_URL: jdbc:postgresql://PostgreSql:5432/sonarqube
SONAR_JDBC_USERNAME: root
SONAR_JDBC_PASSWORD: 123456
JAVA_TOOL_OPTIONS: '-Djava.net.preferIPv6Addresses=true'
SONAR_WEB_JAVAADDITIONALOPTS: '-Djava.net.preferIPv6Addresses=true'
ports:
- 9900:9000
networks:
dev-net:
ipv4_address: 172.28.0.9配置说明
网络模型(Network)
networks:
dev-net:
external: true这里的网络配置是整个架构的关键。external: true 意味着这个 Docker 网络已在外部创建好,Compose 不会尝试创建它,而是直接使用。这种设计的优势:
- 服务间发现:加入同一自定义网络的所有容器,可以通过服务名(如
PostgreSql)或容器名(如SonarQube)相互通信,无需依赖 IP - 跨 Compose 文件共享:多个
docker-compose.yml共享同一个网络——PostgreSQL 可以单独一个 Compose,SonarQube 单独一个 Compose,甚至 MCP Server 也独立运行,只要都在dev-net中就能互相访问 - 固定 IP 分配:自定义网络支持为容器指定静态 IP,这对 MCP 这类需要固定地址的调用方非常友好
- DNS 解析:Docker 内置 DNS 会解析同一网络内的容器名,但 MCP 作为临时容器(
--rm),更适合通过显式 IP 通信,避免依赖 DNS 刷新时机
创建外部网络只需一条命令:
docker network create --subnet=172.28.0.0/16 dev-net这样整个 172.28.0.0/16 网段都可以用来分配固定 IP。
持久化卷挂载
| 路径 | 用途 |
|---|---|
./data | Elasticsearch 索引和 H2 数据 |
./logs | 应用和 ES 运行日志 |
./extensions | 插件安装目录(重启会保留) |
./conf | 覆盖 SonarQube 默认配置 |
data 和 extensions 的持久化尤为重要——前者防止重启后数据丢失,后者避免每次重启重新下载插件。
数据库连接
environment:
SONAR_JDBC_URL: jdbc:postgresql://PostgreSql:5432/sonarqube
SONAR_JDBC_USERNAME: root
SONAR_JDBC_PASSWORD: 123456SonarQube 通过 JDBC 连接 PostgreSQL。连接串中的 PostgreSql 是同一 Docker 网络内 PostgreSQL 容器的服务名(或容器名),Docker 内置 DNS 会自动将其解析为对应 IP。
生产环境务必注意:
- 使用专用数据库用户,不要复用
root - 密码复杂度至少 16 位,包含大小写字母、数字和特殊字符
- 提前创建好
sonarqube数据库,并确保 SonarQube 用户有读写权限
IPv6 与端口映射
environment:
JAVA_TOOL_OPTIONS: '-Djava.net.preferIPv6Addresses=true'
SONAR_WEB_JAVAADDITIONALOPTS: '-Djava.net.preferIPv6Addresses=true'
ports:
- 9900:9000JAVA_TOOL_OPTIONS 是 JVM 级参数,影响 SonarQube 内部所有 Java 组件的网络行为;SONAR_WEB_JAVAADDITIONALOPTS 专门传递给 Web 服务器(Tomcat)实例。如果你运行在纯 IPv6 环境或 Docker 双栈网络中,这两项确保 SonarQube 正确绑定和通信。
端口映射 9900:9000 将容器内 9000 端口映射到宿主机 9900,原因是 SonarQube 的 9000 端口常与其它开发工具(如 Jenkins、Kubernetes dashboard)冲突。修改宿主端口不影响容器间通信——同一网络内容器仍通过 9000 直连。
静态 IP 分配
networks:
dev-net:
ipv4_address: 172.28.0.9为容器分配固定 IP 的主要考虑:
- MCP Server 的稳定性:MCP SonarQube Server 以
docker run --rm方式运行(每次创建新容器),无法依赖容器名 DNS 解析。固定 IP 提供了一个不变的访问端点 - 避免 DNS 缓存问题:临时容器的 DNS 记录可能不会立即在所有节点同步,显式 IP 绕过这一层
- 防火墙白名单:固定 IP 便于在数据库等下游服务中配置访问控制
生成 Token
部署完成后访问 http://localhost:9900,默认凭据 admin/admin。登录后:
- 前往 Administration > Security > Users
- 找到你的用户,在 Tokens 列点击 Update Tokens
- 生成一个 Token,格式如
squ_xxxxxxxxxxxxxxxxxxxxxxxx
这个 Token 将用于 MCP 配置。
Maven 集成:在 Java 项目中运行 SonarQube 分析
对于 Java 项目,最直接的分析方式是通过 Maven 插件。以 mvnd(Maven Daemon,Maven 的加速版)为例:
mvnd sonar:sonar \
-s /Volumes/SSDATA/Develop/.sdkman/candidates/maven/settings.xml \
-Dmaven.repo.local=/Volumes/SSDATA/Develop/.sdkman/candidates/maven/.m2/repository \
-Dsonar.projectKey=mcp-pg-server \
-Dsonar.projectName='mcp-pg-server' \
-Dsonar.host.url=http://172.28.0.9:9000 \
-Dsonar.token=squ_8f2b8a3a6e02ba2709f300be9357d3297a1f85ee各参数说明:
| 参数 | 说明 |
|---|---|
sonar:sonar | Maven SonarQube 插件的分析目标 |
-s settings.xml | 指定 Maven 配置文件路径(配合 SDKMAN 多版本管理) |
maven.repo.local | 自定义本地仓库路径,避免与系统级 Maven 仓库冲突 |
sonar.projectKey | SonarQube 中的项目唯一标识 |
sonar.projectName | SonarQube 中显示的项目名称 |
sonar.host.url | SonarQube 服务地址(需与 docker-compose 中映射的端口一致) |
sonar.token | 上一步生成的访问令牌 |
如果你是标准 mvn 而非 mvnd,去掉 daemon 前缀直接使用即可:
mvn sonar:sonar \
-Dsonar.host.url=http://localhost:9900 \
-Dsonar.token=squ_xxxxxxxxxxxxxxxxxxxxxxxx运行后,Maven 会自动编译项目、执行静态分析,并将结果上报到 SonarQube 服务器。完成后即可在 Web 界面上查看详细的代码质量报告,包括 Bug、漏洞、代码异味、代码重复度、测试覆盖率等指标。
MCP 集成:让 AI 工具调用 SonarQube
MCP(Model Context Protocol) 是 Anthropic 提出的开放协议,让 AI 应用能安全地访问外部工具和数据。通过 MCP,AI 编码工具可以直接在 SonarQube 上创建项目、运行分析、查询结果。
OpenCode 配置
在 OpenCode 的 mcp.json 中添加 SonarQube 服务:
{
"mcp": {
"sonarqube": {
"type": "local",
"command": [
"docker",
"run",
"-i",
"--rm",
"--network",
"dev-net",
"--ip",
"172.28.0.19",
"-e",
"SONARQUBE_URL=http://172.28.0.9:9000",
"-e",
"SONARQUBE_ORG=mcp-pg-server",
"-e",
"SONARQUBE_TOKEN=squ_xxxxxxxxxxxxxxxxxxxxxxxx",
"mcp/sonarqube:latest"
],
"enabled": true
}
}
}关键参数:
| 参数 | 说明 |
|---|---|
--network dev-net | 与 SonarQube 容器同网段 |
--ip 172.28.0.19 | MCP 容器固定 IP,确保网络稳定 |
SONARQUBE_URL | SonarQube 服务地址(容器内 9000 端口) |
SONARQUBE_ORG | SonarQube 组织名称 |
SONARQUBE_TOKEN | 上一步生成的访问令牌 |
工作原理
AI 编码工具 (OpenCode/Cursor)
│
│ MCP Protocol
▼
MCP SonarQube Server (Docker 容器)
│
│ HTTP API
▼
SonarQube (Docker 容器, :9000)
│
│ JDBC
▼
PostgreSQL (外部数据库)当你在 AI 编码工具中编写代码时,可以通过 MCP 工具调用 SonarQube 的能力:
- 创建项目:为新项目在 SonarQube 中创建配置
- 运行分析:提交代码进行静态分析
- 查询结果:获取 Bug、漏洞、代码异味报告
- 获取质量门:检查代码是否通过质量门禁
最佳实践
1. 安全建议
- 专有网络:使用
external网络隔离 SonarQube 和数据库 - Token 管理:避免将 Token 硬编码提交到 Git 仓库,使用环境变量注入
- 防火墙:生产环境限制 9000 端口仅允许内网和白名单 IP 访问
2. 性能优化
- 为 SonarQube 容器分配至少 2GB 内存(ES 堆 + 应用堆)
- 将
extensions/挂载卷持久化,避免重启后重新下载插件 - 生产环境使用独立 PostgreSQL 实例,避免资源争抢
3. MCP 配合使用
在 AI 会话中,可以直接要求 AI 工具:
"帮我分析当前项目的代码质量,在 SonarQube 中创建项目并运行分析"
AI 工具会通过 MCP 调用 SonarQube 自动完成创建项目、上传代码、触发分析、返回结果的全流程。
总结
SonarQube + MCP 的组合,将传统 CI/CD 中的代码质量检查环节,直接带入了 AI 编码的工作流中。在 AI 生成代码越来越普遍的今天,这种实时质量反馈机制能有效减少技术债务,保证项目健康度。