GitLab CI/CDの「キャッシュ」と「アーティファクト」を極めろ:パイプラインを爆速にする設計思想
GitLab CI/CDを使いこなしているつもりでも、パイプラインの実行時間が「数分」から「数十分」に伸びた瞬間、多くのチームは「サーバーのスペック不足」を疑います。しかし、真の原因はインフラではなく、キャッシュとアーティファクトの設計思想の欠如にあることがほとんどです。
今日は、CI/CDパイプラインを「待ち時間」から「フィードバックループの加速装置」へと変貌させる、現場で培った最適化の極意を伝授します。
—
1. 「キャッシュ」と「アーティファクト」の明確な境界線
まずは、この2つの概念を混同している時点で勝負は決まっています。
- キャッシュ (Cache): 「ビルドに使う道具や部品」を置く場所。依存関係(`node_modules`, `.m2`, `vendor`)を指す。消えてもビルドは成功するが、遅くなる。
- アーティファクト (Artifacts): 「ビルドの成果物」。バイナリ、コンパイル後のJS、テストレポートなどを指す。これが消えるとデプロイ先がない。
鉄則:
- キャッシュは「使い捨て可能」なものに使う。
- アーティファクトは「後続ジョブが必ず必要とするもの」に使う。
—
2. キャッシュ戦略:依存関係のダウンロード地獄を脱出する
`node_modules`を毎回ダウンロードしていませんか? それはパイプラインの自殺行為です。GitLab CIのキャッシュは、`key`の設定が全てを握ります。
実践的YAML構成:`cache`の最適化
プロジェクトごとの依存関係をキャッシュ
default:
cache:
# ブランチごとにキャッシュを分離し、汚染を防ぐ
key: ${CI_COMMIT_REF_SLUG}
paths:
- .npm/ # npmのキャッシュディレクトリを指定
policy: pull-push # 基本はpullとpush
特定のジョブでのキャッシュ利用例
install_dependencies:
stage: build
script:
- npm ci –cache .npm –prefer-offline
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .npm/
policy: pull-push # 依存関係が変わる可能性があるので更新
プロのハック: `policy: pull` を活用せよ。テストジョブなどはキャッシュを「読み込むだけ」にして、GitLab RunnerからS3/GCSへのアップロード時間を削減します。
—
3. アーティファクト戦略:ジョブ間のバトンリレー
アーティファクトは、ジョブ間でファイルを渡すための「物理的な通路」です。これを適切に設定しないと、I/Oがボトルネックになります。
ベストプラクティス:`expire_in` と `reports`
無制限に成果物を保存するのはストレージの無駄。また、レポート系は専用の機能を使うのが鉄則です。
build_app:
stage: build
script:
- npm run build
artifacts:
paths:
- dist/ # 成果物
expire_in: 1 week # 成果物は1週間で自動削除(クリーンアップを意識)
reports:
junit: report.xml # テスト結果は専用のreportsで指定し、GitLab UI上で可視化
—
4. 現場で震えるほど役立つ「加速」テクニック
① `cache`の`key`にファイルハッシュを使う
`key: ${CI_COMMIT_REF_SLUG}` だと、新しい依存関係が追加されるたびにキャッシュが古くなります。
`key: files: – package-lock.json` と設定することで、ロックファイルが更新された時だけキャッシュを再構築できます。これが最強の効率化です。
② GitLab Runnerの「プレビルド」キャッシュ
共有Runnerを使っている場合、キャッシュの転送時間がボトルネックになります。自前でRunnerを立てているなら、`docker`ボリュームのキャッシュをホスト側にマウントし、ネットワーク経由のキャッシュ転送をゼロにするのが究極の解です。
③ 神プラグイン:`gitlab-ci-linter`
VS Codeを使っているなら、GitLab Workflow拡張機能は必須です。YAMLの構文チェックだけでなく、CI実行前にローカルでLintを行うことで、「プッシュして失敗→修正してプッシュ」という無駄な往復をゼロにします。
—
5. チーム開発における共有ルール(CI/CDの秩序)
チームでCIを運用する際、以下のルールを`CODEOWNERS`に含め、CIの規約を強制してください。
1. ステージ間の依存関係を明示せよ: `dependencies` キーを使い、必要なアーティファクトのみをダウンロードさせること。デフォルトの「全ジョブの全アーティファクト引き継ぎ」はパイプラインを重くする原因です。
2. パイプラインのタイムアウト設定: 長すぎるジョブは強制停止し、最適化のサインとする。
3. CI変数の秘匿化: 認証情報は必ず`Masked`かつ`Protected`に。CI設定ファイルにベタ書きする人間にはコードレビューで徹底的にダメ出ししてください。
—
最後に:CI/CDは「開発体験(DX)」そのもの
パイプラインの実行時間が1分短縮されることは、チーム全員の1日の生産性を数時間分取り戻すことに直結します。
「とりあえず動く」YAMLを書くステージは卒業しましょう。「いかにキャッシュを再利用し、アーティファクトの移動を最小化するか」。この問いを常に持ち続けることこそ、エンジニアとしての格の違いを見せつけるポイントです。
さあ、今すぐあなたの`.gitlab-ci.yml`を開き、無駄なキャッシュ転送を削ぎ落としてください。その1秒の短縮が、チームの未来を変えます。