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前に推奨)
make docker-ci-checkこれでCI相当のチェックをまとめて実行します:
- コードフォーマットチェック
- ビルド(CIと同じフラグ)
- clang-tidyリント
- 全テスト実行
大きめの変更やLinux依存の変更を入れたときは、push前に実行してください。
2. 個別ステップの実行
# ビルドのみ
make docker-build-linux
# テストのみ
make docker-test-linux
# リントのみ
make docker-lint-linux
# フォーマットチェックのみ
make docker-format-check-linux3. 対話的開発シェル
make docker-dev-shellLinuxコンテナ内で対話的な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-build | Linux Dockerイメージのビルド(他のターゲットから自動実行) |
docker-dev-shell | Linuxコンテナでの対話的シェル |
docker-build-linux | Linuxでプロジェクトをビルド(CIを再現) |
docker-test-linux | Linuxでテストを実行 |
docker-lint-linux | Linuxでclang-tidyを実行 |
docker-format-check-linux | Linuxでフォーマットをチェック |
docker-clean-linux | Linuxでビルドディレクトリをクリーン |
docker-ci-check | 全CIチェックを実行(推奨) |
推奨ワークフロー
パターン1: push前チェック(推奨)
# macOSでの通常開発
make format # コードフォーマット
make build # ビルド確認
make test # テスト実行
# push前のLinux確認
make docker-ci-check # Linux環境で全チェック
# 問題なければコミット
git commit -m "..."
git pushパターン2: 継続的テスト
Linux固有の問題に取り組んでいる場合や頻繁にテストしたい場合:
# ターミナル1: Linuxでビルドを継続
make docker-build-linux
# ターミナル2: Linuxでテストを継続
make docker-test-linux
# または対話的シェルで高速イテレーション
make docker-dev-shell
# コンテナ内: make build && make testパターン3: CI失敗時のデバッグ
CIで特定のエラーが発生した場合:
# 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/ ディレクトリはボリュームとしてマウントされるため、ビルドはインクリメンタルです:
# 初回ビルド: 全コンパイル
make docker-build-linux
# 2回目のビルド: 変更ファイルのみ
make docker-build-linux # ずっと高速!3. 並列テスト
テストは利用可能な全CPUコアを使用して並列実行されます:
make docker-test-linux # $(nproc) コアを使用4. ccache
コンテナはccacheを使用してコンパイルを高速化します。これはビルド間で共有されます。
用語補足
ccache は、同じコンパイル結果を再利用するためのキャッシュです。ヘッダやコンパイルオプションが変わっていないファイルは再コンパイルを省けるため、2回目以降のビルドが速くなります。
トラブルシューティング
問題: "permission denied" エラー
コンテナはrootとして実行されますが、ファイルはユーザーが所有しています。権限の問題が発生した場合:
# ビルドディレクトリをクリーン
make docker-clean-linux
# または手動で
sudo rm -rf build/問題: Dockerイメージが古い
依存関係が変更された場合(新しいLLVMバージョン、新しいライブラリなど):
# 開発イメージを再ビルド
docker build -f support/dev/Dockerfile -t mygramdb-dev:latest --no-cache .問題: ディスク容量
Dockerイメージはディスク容量を消費します。クリーンアップ方法:
# 開発イメージを削除
docker rmi mygramdb-dev:latest
# 未使用のDockerリソースを全てクリーン
docker system prune -a問題: ビルドが遅い
キャッシュを使用してもビルドが遅い場合:
# ccache統計を確認
make docker-dev-shell
ccache --show-stats
# 必要に応じてccacheサイズを増やす(コンテナ内)
ccache --set-config=max_size=1GCI環境の詳細
support/dev/Dockerfile 環境は .github/workflows/ci.yml と一致します:
| コンポーネント | バージョン |
|---|---|
| OS | Ubuntu 22.04 |
| コンパイラ | GCC(デフォルト)+ Clang 18 |
| CMake | aptから最新版 |
| clang-format | 18 |
| clang-tidy | 18 |
| MySQL Client | libmysqlclient-dev |
| ICU | libicu-dev |
| Readline | libreadline-dev |
| カバレッジ | lcov |
| キャッシュ | ccache |
Git Hooksとの連携
push前に自動的にCIチェックを実行するpre-pushフックを追加できます:
# .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
fichmod +x .git/hooks/pre-push高度な使用方法
カスタムCMakeオプション
# 異なるオプションでビルド
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)"特定のテストを実行
docker run --rm -v $(pwd):/workspace -w /workspace mygramdb-dev:latest \
bash -c "cd build && ctest -R 'MyTest.*' --verbose"カバレッジレポートの生成
make docker-dev-shell
# コンテナ内
cd build
make coverage
# coverage/html/index.htmlを表示比較: macOSとLinuxのテスト
| 側面 | macOS (make build) | Linux (make docker-build-linux) |
|---|---|---|
| 速度 | 高速(ネイティブ) | やや遅い(コンテナ化) |
| 環境 | あなたのmacOS | CI環境(Ubuntu 22.04) |
| 用途 | 高速イテレーション | push前の検証 |
| コンパイラ | Clang(macOS) | GCC(Linux) |
| ヘッダ | より寛容 | より厳格(記載漏れを検出) |
推奨: 両方を使用!
- macOS: 迅速な開発用
- Linux: push前の検証用