💡 今日學習目標:學會使用 Docker 容器化技術,在 5 分鐘內架設完成專屬的 SonarQube 免費社群版資安檢測站,並準備好一份明天要拿來開刀的專案。
昨天我們學會在單機 IDE 中使用 SonarQube for IDE 進行即時防護。但當專案變大、或是需要對整個程式庫做完整分析時,我們需要一個中央儀表板(Dashboard),來追蹤整體專案的安全趨勢與健康度。
今天,我們就要用 Docker,花不到 5 分鐘,在你的本機建置好一台 SonarQube Community Build(就是 Day 07 提過的、原本叫 Community Edition 的免費版)。
sysctl vm.max_map_count fs.file-max
官方要求是 vm.max_map_count ≧ 524288、fs.file-max ≧ 131072。
🔑 請注意那個「≧」:這是下限,不是設定值。
很多教學(包括這篇的初版)會叫你直接執行
sudo sysctl -w fs.file-max=131072。但筆者在 Ubuntu 24.04 上實際量到的值是 9,223,372,036,854,775,807,照抄那行指令等於把它調降了。而
vm.max_map_count也有變化:Fedora、Arch、Ubuntu 在 2024 年前後把預設值從65530一口氣提高到 1048576(起因其實是 Wine/Proton 跑現代遊戲會撞到上限)。所以在新版發行版上,這兩項你很可能什麼都不用做。
真的不夠再改。而且別用 sysctl -w,那是暫時的,重開機就沒了。直接寫成永久設定:
sudo tee /etc/sysctl.d/99-sonarqube.conf <<'EOF'
vm.max_map_count=524288
EOF
sudo sysctl --system
(只有在剛剛檢查發現 fs.file-max 真的小於 131072 時,才在上面多加一行 fs.file-max=131072。)
這是新手卡關率最高的一關。如果你的容器啟動後幾秒就自己停掉,
docker logs sonarqube裡看到max virtual memory areas vm.max_map_count [65530] is too low,就是這個原因;那個65530代表你的系統還是舊的預設值。
(Windows / macOS 的 Docker Desktop 已經預設處理好,可以跳過。)
開啟你的 Terminal(終端機)或 PowerShell,輸入以下指令:
docker run -d --name sonarqube \
--restart unless-stopped \
-p 9000:9000 \
-v sonarqube_data:/opt/sonarqube/data \
-v sonarqube_logs:/opt/sonarqube/logs \
-v sonarqube_extensions:/opt/sonarqube/extensions \
sonarqube:community
-d:在背景持續執行(Background Mode)。--name sonarqube:將此容器命名為 sonarqube,之後好操作。--restart unless-stopped:開機時自動啟動,除非你自己手動停掉它。-p 9000:9000:把本機的 9000 埠映射到容器內的 9000 埠。-v sonarqube_*:...:掛載三個資料卷。少了這三行,只要容器被刪掉,你的專案、設定與 Token 就全部消失。這是很多教學會漏掉、但你一定會後悔的一步。sonarqube:community:免費社群版的映像檔。🔑
--restart unless-stopped這一行,是筆者自己踩過兩次才補上的。Day 09 到 Day 11 是一個橫跨三天的練習,中間你一定會關機至少一次。而容器預設不會跟著開機一起起來:隔天你打開
localhost:9000,只會看到「無法連線」。那個畫面不會告訴你原因,你會開始懷疑是不是昨天哪個步驟做錯了,然後把整篇重做一次。加上這一行就不會發生。
如果你已經照舊指令建好容器了,不用重建,直接對現有的容器改就生效:
docker update --restart unless-stopped sonarqube
⚠️ 不要用網路上常見的
sonarqube:lts-community。那個標籤停留在舊的 LTS 線上,已經將近一年沒有更新了;現在免費版的正確標籤就是community。(如果你偏好長期支援版本,現在有
2026-lta-community這個標籤可用;但本系列用community就好,它拿到的是最新的 Community Build。)
http://localhost:9000。admin
admin

🧐 畫面上寫的是「SonarQube Server」,跟我們說的「Community Build」是同一個東西嗎? 是的。
SonarQube Server 指的是「自架版」這整條產品線,Community Build 則是它底下那個免費的版本。就像「汽車」跟「某個車款」的關係,不是兩個不同的東西。你架起來的這台,正式的說法是「SonarQube Server 的 Community Build」。
🔎 如果瀏覽器連不上,先用
docker logs -f sonarqube看啟動進度。看到SonarQube is operational才算真的起來了;在那之前連線會被拒絕,不是你設定錯了。
登入成功後,系統會自動要求你變更 admin 的預設密碼,而且不改就進不去。

🛡️ 資安實踐 alert:將系統預設密碼改為強密碼,本身就是安全組態防範(Security Misconfiguration)的核心原則之一!
🧐 順便看一下畫面上那串密碼規則,它剛好是個很好的教材。
SonarQube 要求「至少 12 個字元、含大寫、小寫、數字、特殊符號」。這是非常典型的密碼政策,你在無數系統上都看過。
但 NIST 在 2025 年 7 月定稿的 SP 800-63B-4 裡,用
SHALL NOT明文禁止了「強制字元組合規則」。理由是這種規則會逼使用者採用可預測的替換方式(a➔@、o➔0),製造出「看起來很複雜、實際上很好猜」的密碼。這不是說 SonarQube 做錯了。標準更新到工具跟上,中間有很長的時間差,而且改動預設政策會影響所有既有使用者。但它剛好示範了一件事:你在真實系統上看到的做法,不一定就是現在最新的建議。 Day 20 我們會完整處理這個題目。
為了讓後續的掃描工具能把結果上傳到這個 SonarQube 伺服器,我們需要發行一組認證 Token:
my-local-scanner)。Global Analysis Token。
這個畫面上有三個容易被滑過去、但值得停一下的細節:
🛡️ 這裡就是一個現成的實戰練習:這串 Token 等同於存取這台伺服器的鑰匙。它不該被貼進 Slack、不該進版本庫、更不該出現在你的鐵人賽截圖裡。
明天我們會把它放進環境變數來使用,這正是 Day 08 那條「硬編碼機密」規則想教你的事。
🔑 而且塗黑只是防守,不是根除。 上面那張圖裡的 Token 雖然已經塗掉,但筆者的實際做法是:截完圖就直接按下那顆
Revoke讓它作廢,再產一組新的給明天用。塗黑防的是「有人看到」,撤銷防的是「就算被看到也沒用」。只要成本允許,永遠選後者。
檢測站架好了,但它現在是空的。明天要掃什麼? 我們先把待宰的羔羊準備好。
建立一個專案資料夾:
mkdir -p ~/my-first-security-project
cd ~/my-first-security-project
📌 Windows 使用者請自己找一個好記的位置,例如
D:\sonar-lab\my-first-security-project。等一下要記住這個絕對路徑,明天掛載目錄時會用到。
在裡面放一支 checksum.js。這段程式碼在計算檔案的完整性校驗碼,是真實專案裡到處都有的東西:
cat > checksum.js <<'EOF'
const crypto = require("node:crypto");
// 計算檔案的完整性校驗碼(checksum)
function generateChecksum(fileBuffer) {
// ⚠️ MD5 已被證實可以人為製造碰撞
return crypto.createHash("md5").update(fileBuffer).digest("hex");
}
module.exports = { generateChecksum };
EOF
如果你昨天選的是 Python 路線,就改放 checksum.py:
cat > checksum.py <<'EOF'
import hashlib
def generate_checksum(file_bytes: bytes) -> str:
# ⚠️ MD5 已被證實可以人為製造碰撞
return hashlib.md5(file_bytes).hexdigest()
EOF
💻 Windows / PowerShell 使用者請注意:上面那幾行是 Linux 與 macOS 的寫法,
mkdir -p與cat > 檔名 <<'EOF'(here-document)在 PowerShell 都不能用。最省事的做法是:直接用你 Day 08 裝好外掛的那個編輯器新增檔案、把程式碼貼進去、存檔就好。 反正等一下也要用編輯器來改它。重點只有兩個:資料夾位置你要記得,以及副檔名必須正確。
順手把昨天 Day 08 那支 test.js(或 test.py)也複製進這個資料夾,用你修好之後的乾淨版本。這樣明天的掃描結果會很好讀:乾淨的那支一筆問題都沒有,只有 checksum.js 會亮起來,對照非常清楚。
🧨 這一次,請不要修它。
昨天在 IDE 裡,你一看到底線就順手把問題修掉了,那是對的習慣。但今天這支
checksum.js要故意留著:
- 明天(Day 10),我們要看它在伺服器的儀表板上被算成幾分、歸在哪一類。
- 後天(Day 11),我們要走完一次完整的審查流程,再親手把它修掉。
換句話說,這是刻意種下的一個問題,用來讓你看清楚整條「掃描 ➔ 判讀 ➔ 修復」的流水線。真實專案裡,這種程式碼是不小心寫下的;在這裡,它是教材。
用上面這個指令跑起來的 SonarQube,內建的是一套 H2 嵌入式資料庫。它的定位很明確:
換句話說,今天架的這台是你的練習場。等哪天要把它變成團隊真正依賴的服務,再花時間接上 PostgreSQL 就好,指令一樣是一段 docker compose。
admin/admin 是攻擊者掃到管理介面後的第一發子彈,而你剛剛親手把它換掉了,這就是最小成本的資安實踐。💬 明日預告:【Day 10】【動手做】把程式碼丟進去掃描!解讀 SonarQube 的資安評分與漏洞報告
伺服器架好了!明天我們將親自執行第一次掃描,並教你看懂 A~E 級資安報告!