🐳

SonarQube を Docker + npm で導入!フロントエンドコードを静的解析する手順まとめ

に公開

SonarQubeの概要

SonarQubeとは

SonarQube Gitリポジトリの README より

SonarQube provides the capability to not only show the health of an application but also to highlight issues newly introduced. With a Quality Gate in place, you can achieve Clean Code and therefore improve code quality systematically.

日本語訳:SonarQube はアプリケーションの「現在の健全性」を可視化するだけでなく、「新たに導入された問題」を検出することもできます。
さらに、Quality Gate(品質基準)を設定することで、Clean Code(読みやすく保守性の高いコード)を継続的に目指せる仕組みになっています。

このように、SonarQube はコード品質を一時的に良くするツールではなく、継続的に品質を保ち、改善し続けるためのツールです。

構成要素

SonarQube には、サーバーとスキャナーという2つの構成要素が登場します。

SonarQube Server

SonarQube Server は、コード解析結果の保存・可視化・評価を担っています。

主な役割は以下のとおりです。

  • 分析結果のダッシュボード表示(Web UI)

  • プロジェクト設定(Quality Gate やルールの適用)

  • スキャナーから送られてくるデータの受け取り・保存

  • Quality Gateの評価や、警告・バグの可視化

今回は、このサーバーを Docker コンテナで構築して稼働させます。

SonarScanner

SonarScanner は、プロジェクトのコードを分析して、SonarQube Server に送信するクライアントツールです。

主な役割は以下のとおりです。

  • プロジェクトの静的解析を実行する

  • ローカルまたはCIの設定ファイルから解析パラメータを読み取る

  • 必要な解析用バイナリファイルを SonarQube Server から取得・キャッシュ

  • SonarQube Server にプロジェクト設定やルールの問い合わせを行う

  • 解析結果を SonarQube Server に送信し、解析の完了を通知する

今回は、フロントエンドコードの解析をするので、Node.js 環境で動作する、@sonar/scan という npm を使います。

動作フロー

公式ドキュメントに掲載されていた図が分かりやすかったので、引用させてもらいます。

Introduction to the SonarScanner for NPMより引用

  1. npm script や CI パイプラインなどからSonarScanner を起動

  2. sonar-project.properties に記述されたパラメータや、環境変数などを読み取る

  3. 分析に必要な解析ツール群(バイナリファイル)を SonarQube サーバーからダウンロードして、ローカルにキャッシュ

  4. SonarQube サーバー上のプロジェクト設定(ルール、Quality Gateなど)を取得

  5. コードの解析を実行

  6. 解析が終わると、CIパイプラインやビルドプロセスに「完了」を通知

SonarQubeの環境構築

今回は、SonarQube が公式に提供している Docker イメージを利用して、SonarQube サーバーを立ち上げます。また、SonarQube は分析データや各種設定情報を内部で保持するためのデータベースとして PostgreSQL を使用します。
本記事では、docker-compose を用いて、PostgreSQL 連携込みの最小構成の SonarQube 環境をセットアップする手順を紹介します。

DockerでSonarQubeとPostgreSQLコンテナを起動する

SonarQube の公式DockerイメージのGitリポジトリに、SonarQube + PostgreSQL 構成の docker-cmpose.yml があったので参考にしています。

docker-compose.yaml
docker-compose.yaml
services:
  sonarqube:
    image: sonarqube:community
    hostname: sonarqube
    container_name: sonarqube
    read_only: true
    depends_on:
      db:
        condition: service_healthy
    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
      - sonarqube_temp:/opt/sonarqube/temp
    ports:
      - "9000:9000"
    networks:
      - ipv4
  db:
    image: postgres:17
    healthcheck:
      test: [ "CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}" ]
      interval: 10s
      timeout: 5s
      retries: 5
    hostname: postgresql
    container_name: postgresql
    environment:
      POSTGRES_USER: sonar
      POSTGRES_PASSWORD: sonar
      POSTGRES_DB: sonar
    volumes:
      - postgresql:/var/lib/postgresql
      - postgresql_data:/var/lib/postgresql/data
    networks:
      - ipv4

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

networks:
  ipv4:
    driver: bridge
    enable_ipv6: false
  dual:
    driver: bridge
    enable_ipv6: true
    ipam:
      config:
        - subnet: "192.168.2.0/24"
          gateway: "192.168.2.1"
        - subnet: "2001:db8:2::/64"
          gateway: "2001:db8:2::1"

PostgreSQL コンテナが「使える状態」になるまで待ってから SonarQube を起動するようになっているので、SonarQube の起動時エラー(DBに接続できないなど)を回避できるようになっている点など、さすが公式ですね!

また、公式ではNETWORK_TYPEという環境変数を使って、.env ファイルなどで柔軟な切り替えができるようにしていましたが、今回は切り替え予定がないので、networks: - ipv4 と直接指定しました。

起動方法

docker compose up -d

起動に成功すれば、下記のように表示されます。

[+] Running 3/3
 ✔ Network my-project_ipv4  Created                                                                                                                                               0.1s 
 ✔ Container postgresql       Healthy                                                                                                                                               0.1s 
 ✔ Container sonarqube        Started

ブラウザでhttp://localhost:9000にアクセスすると、SonarQube のログイン画面が表示されます。

初回は、LoginとPasswordともに admin を入力するとログインできます。
その後、Passwordの変更を求められるので指示に従い変更します。

続いて、Projectの設定をします。

1.「Create a local project」を選択する。

  1. Project名を入力する。

  2. 新しいコードの定義を設定する。一般的なProjectであれば、「Use the global setting」を選択して、「Create project」をクリックする。

  3. 分析の実行方法を設定する。今回はローカルでスキャンを実行するだけなので、「Locally」を選択します。

  4. トークン名と期限を設定する。今回はローカル環境でサーバーを立てているため、「No expiration(期限なし)」を選択します。

  5. トークンが生成されます。このトークンはスキャンの実行時に必要になるのでコピーしておきます。

プロジェクトにSonarScannerをインストールして実行できるようにする

npm から @sonar/scanをインストールする。

npm install -D @sonar/scan

スキャン用の設定ファイルを追加する

sonar-project.properties
# SonarQube プロジェクト設定ファイル
sonar.projectKey=my-project
sonar.projectName=My project

sonar.sources=src

sonar.host.url=http://localhost:9000
sonar.token=your-token-here

※ 今回は説明の都合上、トークンを直接記述していますが、実際の運用では環境変数で管理することを推奨します。
※ プロパティの詳細は下記を参照してください。
Analysis parameters

package.jsonにスクリプトを追記する。

package.json
"scripts": {
  "sonar": "sonar-scanner"
},

スキャンを実行する

下記のコマンドを実行します。

npm run sonar

スキャンに成功すれば、下記のログが出力されます。

[INFO]  ScannerEngine: ANALYSIS SUCCESSFUL, you can find the results at: http://localhost:9000/dashboard?id=my-project
[INFO]  ScannerEngine: Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report
[INFO]  ScannerEngine: More about the report processing at http://localhost:9000/api/ce/task?id=eda54adf-2047-4c51-9a0d-bd8598ed7a5f
[INFO]  ScannerEngine: Analysis total time: 7.120 s
[INFO]  ScannerEngine: SonarScanner Engine completed successfully

SonarQubeサーバーのダッシュボードにアクセスすると実行結果を見ることができます。
http://localhost:9000/dashboard?id=my-project

ダッシュボードの解説

ダッシュボードには、measure(指標)とmetrics(測定基準)の概要が表示されています。

  • Security(セキュリティ)
     ソフトウェアが不正なアクセス、使用、または破壊から保護されているかどうかの指標です。

  • Reliability(信頼性)
     一定の条件下で、一定期間にわたってソフトウェアがその性能を維持できるかどうかの指標です。

  • Maintainability(保守性)
     ソフトウェアのコードを修正・改善・理解することの容易さを指します。

  • Coverage(カバレッジ)
     実行可能なコード行と条件式(分岐)に関するカバレッジ統計に基づいて測定されます。

  • Duplications(重複度)
     同一または非常によく似たコードの重複箇所の割合を示します。
     コードのコピー&ペーストによる重複は保守性やバグ修正の難易度を上げるため、低く抑えることが望まれます。

  • Security Hotspots(セキュリティ・ホットスポット)
     セキュリティ上の注意が必要なコード領域です。
     これらは自動的に「脆弱性」とは判定されませんが、開発者による手動レビューを推奨される箇所です(例:暗号処理、認証関連など)。

※詳細は、下記を参照してください。
Understanding measures and metrics

まとめ

今回は、以下の2点について解説しました。

  • SonarQube の基本構成(Server / Scanner)
  • Docker を使ってローカルに SonarQube + PostgreSQL 環境を構築し、プロジェクトをスキャンしてダッシュボードで結果を確認する方法

今後は、GitHub Actions などの CI パイプラインへの統合や、VS Code の拡張機能 SonarQube for IDE を活用したコード品質チェックの補助などもキャッチアップしていきたいと思います!

参考

Discussion