Skip to content

DockerによるLinux CI テスト

概要

このガイドでは、GitHub Actions CI と同じLinux環境でコードをテストし、プラットフォーム固有の問題(ヘッダの記載漏れやコンパイラの違い)をpushする前に検出する方法を説明します。

このページを読むタイミング

macOSで開発していて、GitHub ActionsやLinux上のビルド失敗を事前に潰したい場合に使います。通常の利用者がMygramDBをインストールするための手順ではありません。

問題

macOSで開発している場合、以下の問題がLinux環境でのみ発生することがあります:

  • ヘッダファイルの記載漏れ (例: <cstdint>, <climits>)
  • コンパイラの挙動の違い (Clang vs GCC)
  • ライブラリバージョンの違い
  • パス処理の違い

これらの問題はローカルのmacOSでは見えず、push後のCIで初めて失敗することがあります。

解決策

GitHub Actions CI環境(Ubuntu 22.04と同じ依存関係)をDockerで再現し、手元でLinuxビルド・リント・テストを実行できるようにしています。

クイックスタート

1. フルCIチェック(push前に推奨)

bash
make docker-ci-check

これでCI相当のチェックをまとめて実行します:

  1. コードフォーマットチェック
  2. ビルド(CIと同じフラグ)
  3. clang-tidyリント
  4. 全テスト実行

大きめの変更やLinux依存の変更を入れたときは、push前に実行してください。

2. 個別ステップの実行

bash
# ビルドのみ
make docker-build-linux

# テストのみ
make docker-test-linux

# リントのみ
make docker-lint-linux

# フォーマットチェックのみ
make docker-format-check-linux

3. 対話的開発シェル

bash
make docker-dev-shell

Linuxコンテナ内で対話的なbashシェルが起動し、手動でコマンドを実行できます:

bash
# コンテナ内で
make build
make test
make lint
./build/bin/mygramdb --help

仕組み

Dockerイメージ: support/dev/Dockerfile

support/dev/Dockerfile は、GitHub Actions CI環境に近いLinux開発環境を作成します:

  • ベース: Ubuntu 22.04
  • コンパイラ: GCC(CIと同じ)
  • ツール: clang-format-18, clang-tidy-18, ccache
  • 依存関係: libmysqlclient-dev, libicu-dev など

Makefileターゲット

全てのLinuxテストターゲットは docker-*-linux パターンに従います:

ターゲット説明
docker-dev-buildLinux Dockerイメージのビルド(他のターゲットから自動実行)
docker-dev-shellLinuxコンテナでの対話的シェル
docker-build-linuxLinuxでプロジェクトをビルド(CIを再現)
docker-test-linuxLinuxでテストを実行
docker-lint-linuxLinuxでclang-tidyを実行
docker-format-check-linuxLinuxでフォーマットをチェック
docker-clean-linuxLinuxでビルドディレクトリをクリーン
docker-ci-check全CIチェックを実行(推奨)

推奨ワークフロー

パターン1: push前チェック(推奨)

bash
# macOSでの通常開発
make format              # コードフォーマット
make build              # ビルド確認
make test               # テスト実行

# push前のLinux確認
make docker-ci-check    # Linux環境で全チェック

# 問題なければコミット
git commit -m "..."
git push

パターン2: 継続的テスト

Linux固有の問題に取り組んでいる場合や頻繁にテストしたい場合:

bash
# ターミナル1: Linuxでビルドを継続
make docker-build-linux

# ターミナル2: Linuxでテストを継続
make docker-test-linux

# または対話的シェルで高速イテレーション
make docker-dev-shell
# コンテナ内: make build && make test

パターン3: CI失敗時のデバッグ

CIで特定のエラーが発生した場合:

bash
# CI環境を正確に再現
make docker-dev-shell

# コンテナ内で失敗したステップを実行
cd build
cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=ON -DENABLE_COVERAGE=ON -DUSE_ICU=ON -DUSE_MYSQL=ON ..
make -j$(nproc)
make lint

# 問題を修正後、検証
exit
make docker-ci-check

パフォーマンスのヒント

1. イメージキャッシング

Dockerイメージは初回ビルド後にキャッシュされます。以降の実行はずっと高速です:

  • 初回: ~5-10分(LLVMや依存関係のダウンロードとインストール)
  • 2回目以降: ~10-30秒(コードのビルドのみ)

2. インクリメンタルビルド

build/ ディレクトリはボリュームとしてマウントされるため、ビルドはインクリメンタルです:

bash
# 初回ビルド: 全コンパイル
make docker-build-linux

# 2回目のビルド: 変更ファイルのみ
make docker-build-linux  # ずっと高速!

3. 並列テスト

テストは利用可能な全CPUコアを使用して並列実行されます:

bash
make docker-test-linux  # $(nproc) コアを使用

4. ccache

コンテナはccacheを使用してコンパイルを高速化します。これはビルド間で共有されます。

用語補足

ccache は、同じコンパイル結果を再利用するためのキャッシュです。ヘッダやコンパイルオプションが変わっていないファイルは再コンパイルを省けるため、2回目以降のビルドが速くなります。

トラブルシューティング

問題: "permission denied" エラー

コンテナはrootとして実行されますが、ファイルはユーザーが所有しています。権限の問題が発生した場合:

bash
# ビルドディレクトリをクリーン
make docker-clean-linux

# または手動で
sudo rm -rf build/

問題: Dockerイメージが古い

依存関係が変更された場合(新しいLLVMバージョン、新しいライブラリなど):

bash
# 開発イメージを再ビルド
docker build -f support/dev/Dockerfile -t mygramdb-dev:latest --no-cache .

問題: ディスク容量

Dockerイメージはディスク容量を消費します。クリーンアップ方法:

bash
# 開発イメージを削除
docker rmi mygramdb-dev:latest

# 未使用のDockerリソースを全てクリーン
docker system prune -a

問題: ビルドが遅い

キャッシュを使用してもビルドが遅い場合:

bash
# ccache統計を確認
make docker-dev-shell
ccache --show-stats

# 必要に応じてccacheサイズを増やす(コンテナ内)
ccache --set-config=max_size=1G

CI環境の詳細

support/dev/Dockerfile 環境は .github/workflows/ci.yml と一致します:

コンポーネントバージョン
OSUbuntu 22.04
コンパイラGCC(デフォルト)+ Clang 18
CMakeaptから最新版
clang-format18
clang-tidy18
MySQL Clientlibmysqlclient-dev
ICUlibicu-dev
Readlinelibreadline-dev
カバレッジlcov
キャッシュccache

Git Hooksとの連携

push前に自動的にCIチェックを実行するpre-pushフックを追加できます:

bash
# .git/hooks/pre-push
#!/bin/bash
echo "Running CI checks before push..."
make docker-ci-check
if [ $? -ne 0 ]; then
    echo "CI checks failed. Push aborted."
    exit 1
fi
bash
chmod +x .git/hooks/pre-push

高度な使用方法

カスタムCMakeオプション

bash
# 異なるオプションでビルド
docker run --rm -v $(pwd):/workspace -w /workspace mygramdb-dev:latest \
    bash -c "mkdir -p build && cd build && \
    cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_ASAN=ON .. && \
    make -j$(nproc)"

特定のテストを実行

bash
docker run --rm -v $(pwd):/workspace -w /workspace mygramdb-dev:latest \
    bash -c "cd build && ctest -R 'MyTest.*' --verbose"

カバレッジレポートの生成

bash
make docker-dev-shell
# コンテナ内
cd build
make coverage
# coverage/html/index.htmlを表示

比較: macOSとLinuxのテスト

側面macOS (make build)Linux (make docker-build-linux)
速度高速(ネイティブ)やや遅い(コンテナ化)
環境あなたのmacOSCI環境(Ubuntu 22.04)
用途高速イテレーションpush前の検証
コンパイラClang(macOS)GCC(Linux)
ヘッダより寛容より厳格(記載漏れを検出)

推奨: 両方を使用!

  • macOS: 迅速な開発用
  • Linux: push前の検証用

関連ドキュメント