首頁

目前文章總數:172 篇

  

最後更新:2025年 03月 22日

0013. Ubuntu 搭建 SonarQube - 建構企業級程式碼品質把關流程:容器化指南

日期:2025年 01月 25日

標籤: Linux Ubuntu SonarQube Mysql Web Asp.NET Core Web MVC PostgreSQL

摘要:資訊筆記


應用所需:1. Linux 主機(本篇 Linux Ubuntu 22.04 作業系統)
     2. 已安裝 Docker
     3. 已安裝 Dotnet SDK 8.0 以上版本(本篇範例使用)
解決問題:如何在 Ubuntu 上搭建 CodeReview 的 Server ,協助檢查代碼品質,讓 CodeReview 可將更多時間關注於產品業務邏輯 (本篇用 DotNet Core)
     2. 如何使用 SonarQube 排查程式碼
範例檔案:MinIO WebSite 範例
基本介紹:本篇分為 4 大部分。
第一部分:介紹 SonarQube
第二部分:安裝 SonarQube
第三部分:配置 SonarQube & 說明 PostgreSQL
第四部分:專案代碼檢查 & 修正






第一部分:介紹 SonarQube

Step 1:介紹

官網SonarQube維護程式品質的伺服器,官方資訊:

Your code is a business asset. Achieve the highest value from your code by reaching a state of Clean Code with SonarQube Server.


簡單說:SonarQube 是開源的程式碼質量管理平台,它可以持續分析和測量程式碼的技術品質,從 Bug、代碼氣味(Code Smells)到安全漏洞都能夠進行自動化檢測。

Step 2:收費價格

對於開發者,可以先選擇免費方案,以下列出可用功能,基本上一個小型團隊是很夠用

1. 可掃描 1 個私人專案 50,000 行程式碼
2. 無限掃描共用項目 (開源專案,EX: Github 上 Public)
3. 支援 30 種程式語言
4. 最多 5 位用戶共用
5. 問題檢測與靜態應用安全測試 (SAST)
6. 主分支與 Pull Request 的分析 (程式碼,可以針對主分支,以及 Action 再 Pull Request)
7. 支援與 DevOps 工具(如 GitHub、GitLab、Bitbucket)集成,無縫融入 CI/CD 工作流程。



Step 3:使用限制

官網SonarQube 文件(Database 需求頁)資訊,有限制安裝需求:
以下是最低限制:

1. 記憶體 4GB
2. 64Bit 系統,2 核心
3. 至少 30GB 硬碟空間
4. 最多 5 位用戶共用
5. 需安裝資料庫,支援 PostgreSQL、Microsoft SQL server、Oracle


因為效能上的考量 SonarQube 最新版已經不支援 Mysql,但在 DockerCompose 整合下,DB 的安裝已經不會花太多時間。



第二部分:安裝 SonarQube

Step 1:建立 DockerCompose

先進入 Ubuntu 主機上,新建以下 DockerCompose.yml 檔案,內容如下:
以下有將宿主機 Port 設定為 9100 (預設是 9000)
並且安裝 postgres 資料庫,這是免費的 Database ,開出的 Port 為 5432

version: "3"
services:
  sonarqube:
    image: sonarqube:latest
    container_name: sonarqube
    depends_on:
      - db
    environment:
      SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar
      SONAR_JDBC_USERNAME: sonar
      SONAR_JDBC_PASSWORD: sonar
    volumes:
      - sonarqube_data:/opt/sonarqube/data
      - sonarqube_extensions:/opt/sonarqube/extensions
      - sonarqube_logs:/opt/sonarqube/logs
    ports:
      - "9100:9000"
    networks:
      - sonarnet
    ulimits:
      nproc: 131072
      nofile:
        soft: 65536
        hard: 131072

  db:
    image: postgres:12
    container_name: sonarqube_db
    environment:
      POSTGRES_USER: sonar
      POSTGRES_PASSWORD: sonar
      POSTGRES_DB: sonar
        ports:
      - "5432:5432"
    volumes:
      - postgresql:/var/lib/postgresql
      - postgresql_data:/var/lib/postgresql/data
    networks:
      - sonarnet

volumes:
  sonarqube_data:
  sonarqube_extensions:
  sonarqube_logs:
  postgresql:
  postgresql_data:

networks:
  sonarnet:
    driver: bridge
   



Step 2:開啟 sysctl.conf 檔案

進入以下目錄,開啟檔案 :
※這是在編輯 Linux 系統的核心參數配置檔案

/etc/sysctl.conf



Step 3:更新 sysctl.conf

將以下設定貼上

vm.max_map_count=262144
fs.file-max=131072


vm.max_map_count=262144 這是虛擬記憶體的配置,如果這個值太小,SonarQube 可能會出現 “mmap failed” 錯誤
fs.file-max=131072 這是系統允許開啟的檔案描述符的最大數量,131072 代表系統可以同時開啟約 13 萬個檔案



Step 4:生效 sysctl.conf

輸入以下指令讓 sysctl.conf 的配置重啟生效:

sudo sysctl -p


Step 5:生效 sysctl.conf

輸入以下指令讓 sysctl.conf 的配置重啟生效:

sudo sysctl -p


Step 6:安裝 DockerCompose

進入以下目錄 cd /louisTemp/sonarqube
並且輸入安裝指令:

sudo docker-compose up -d



Step 7:安裝完成

可以在 Portainer 或者輸入以下指令檢查容器:

docker ps -a


可以看到 SonarQube 與 Database 都已容器化啟動

Step 8:檢查 Database - 連線

DockerCompose.yml 中有建立資料庫的帳號密碼,可以參考 .yml 檔案,嘗試連線

POSTGRES_USER: sonar
POSTGRES_PASSWORD: sonar
POSTGRES_DB: sonar



Step 9:檢查 Database - 完成

可以看到預設的資料表都會自動建立



第三部分:配置 SonarQube & 說明 PostgreSQL

Step 1:開啟 WebUI

依照自己主機的位置,可以輸入對應的 IP + Port 號進入管理介面

http://192.168.51.28:9100/


預設帳號密碼都是以下:

帳號: admin
密碼: admin



Step 2:強制更改密碼

然後系統會強制更新密碼

Step 3:新建本地專案 - 1

這邊範例說明,因此選擇新建本地專案

Step 4:新建本地專案 - 2

專案名稱、Key、分支名稱
※如果是整合 CICD ,main 分支位置很重要,需要正確

Step 5:新建本地專案 - 3

選擇設定的地方,可以先選擇 Use the golbal setting,繼續下一步

Step 5:專案設置分析語言 - 設定

接著選擇 Locally

Step 6:產生 Token

選擇 Generate 產生 Token

Step 7:紀錄 Token

產生出 Token 後,可以接著 Continue

Step 8:專案設置分析語言 - 選擇

選擇 .Net ,如果是自己的團隊專案,可以再依照需要設定

Step 9:安裝提示步驟

通常這 4 個指令只會在 CI 上配置,因為我們要模擬開發者自己本機,所以要從自己的作業系統執行這 4 項指令

Step 10:.Net 測試專案目錄下

範例檔案:MinIO WebSite 範例先進入其目錄

Step 11:.Net 測試專案目錄下 - 添加 GUID

專案可能沒有 GUID ,如果沒有就需要自行添加。

<PropertyGroup>
    <ProjectGuid>{Your-GUID-Here}</ProjectGuid>
</PropertyGroup>



Step 12:安裝提示步驟 - 步驟1

進入 Windows CMD ,將 Step 10 的第 1 步驟指令 Copy
這會將 SonarQube 的 Asp.net Core 的掃描安裝

Step 13:安裝提示步驟 - 步驟2

進入 Windows CMD ,將 Step 10 的第 2 步驟指令 Copy
這會掃描指定的專案代碼,一定要在 .csporj 或 .sln 的路徑下

Step 14:安裝提示步驟 - 步驟3, 4

進入 Windows CMD ,將 Step 10 的第 3 步驟指令 Copy
第 3 是建置代碼
第 4 完成後如下,會將結果送出到 SonarQube 的遠端機器上

Step 15:安裝提示步驟 - 步驟3, 4

進入 Windows CMD ,將 Step 10 的第 3 步驟指令 Copy
第 3 是建置代碼
第 4 完成後如下,會將結果送出到 SonarQube 的遠端機器上

Step 16:SonarQube - 分析完成

在回到 WebUI 上,可以發現掃描的結果,有 1 個可靠性品質評分為 E ,有 11 個可維護性品質評分為A



第四部分:專案代碼檢查 & 修正

Step 1:可維護性校正 - 來源

打開 SonarQube 的左側項目,會出現每一筆幫您分析的結果
以第 1 筆為例,我的代碼 _teachers 這個變數應改為 Readonly

Step 2:可維護性校正 - 建議

點擊進去,還會有更詳細的代碼位置校正

Step 3:可維護性校正 - 調整&說明

我們將 ReadOnly 補上修正

private readonly List<TeacherModel> _teachers = new List<TeacherModel>();


原因:

這種設計的好處是:

確保物件初始化後,重要的字段引用不會被改變
減少程式的不可預測性
使代碼意圖更清晰:這個字段的引用一旦設定就不應改變
有助於實現不可變性(immutability)原則


總之這就像是在說:”這個容器一旦建立好,就只能改變裡面的東西,而不能換成另一個容器”。

Step 4:可靠性校正 - 建議

這就比較嚴重了,在 Dispose 釋放資源的地方,要避免遞回 recursion



Step 5:可靠性校正 - 調整&說明

正規的做法如下

1. 檢查是否已經釋放
2. 避免在 Dispose 中遞迴調用自己
3. 要有適當的釋放邏輯(bool 實現)
public class MyClass : IDisposable
{
    private bool _disposed = false;  // 追蹤是否已經釋放

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                // 釋放受控資源(managed resources)
                // 例如:關閉檔案、釋放其他 IDisposable 物件等
            }

            // 釋放非受控資源(unmanaged resources)
            // 設置大型欄位為 null
            
            _disposed = true;
        }
    }
}


Step 6:再次掃描

調整並簽入後,在依序執行 SonarQube 的掃瞄步驟 (開發者本機,執行 Windows CMD):


1. 掃描(將單元測試覆蓋率關閉)

dotnet sonarscanner begin /k:"TestDotnetCoreProject" /d:sonar.host.url="http://192.168.51.28:9100" /d:sonar.token="sqp_b40f5b8096fb8cdb39c40da8f3634e96fcab6b8b" /d:sonar.scanner.scanAll=false /d:sonar.scm.disabled=true /d:sonar.coverage.exclusions="**/*" /d:sonar.coverage.enabled=false


2. 建置代碼

dotnet build


3. 上傳

dotnet sonarscanner end /d:sonar.token="sqp_b40f5b8096fb8cdb39c40da8f3634e96fcab6b8b"


Step 7:完成

可以得到所有項目的評分都為 A 的好成果 (可維護性評分影響較低,基本上維護性還需要依賴團隊規範)