こんにちは!日々のCI/CDパイプラインの待ち時間に、コーヒーを何杯もおかわりしていませんか?
「たかがビルド、されどビルド」。塵も積もれば山となり、チーム全体で失う開発時間は膨大です。
今回は、GitLab CI/CDの心臓部とも言える「キャッシュ(Cache)」と「アーティファクト(Artifacts)」の正しい使い分けについて、現場で即効性のある極限の知見をお伝えします。
これをマスターすれば、冗長なダウンロード地獄から抜け出し、パイプラインの実行時間を劇的に短縮できるようになりますよ。さあ、一緒にスマートな自動化の世界へ踏み出しましょう!
—
1. そもそも「キャッシュ」と「アーティファクト」は何が違うのか?
GitLab CI/CD初心者が最初にハマる罠が、「キャッシュとアーティファクトの混同」です。まずはこの2つの本質的な違いを、役割という観点からクリアに整理しましょう。
| 比較項目 | キャッシュ (Cache) | アーティファクト (Artifacts) |
| :— | :— | :— |
| 主な目的 | 外部依存関係の再利用(ビルド高速化) | ジョブ間での成果物の受け渡し(デプロイ等) |
| データの出どころ | 外部(npm, Maven, Pipなどのパッケージレジストリ) | 自ジョブが生成したファイル(バイナリ、HTMLなど) |
| 保存場所 | GitLab Runnerのローカル(またはS3等のリモートキャッシュ) | GitLabサーバー(プロジェクトのストレージを消費) |
| 消えて困るか? | 消えても困らない(再ダウンロードすれば復活する) | 消えたら困る(ビルドの成果物そのものだから) |
🧠 先輩からの直感的アドバイス
- 「ネットから持ってきた重たいライブラリたち」 は キャッシュ に入れる。
- 「自分たちがコードを書いてコンパイルした成果物」 は アーティファクト として次のジョブにバトンタッチする。
この原則さえ守っていれば、設計で迷うことはありません。
—
2. 依存関係のダウンロード時間を激減させる「キャッシュ」の極意
まずはキャッシュです。Node.jsの `node_modules` や Pythonの `venv` など、毎回ゼロからダウンロードしていると、それだけで数分が無駄になります。
以下の `.gitlab-ci.yml` を見てください。これが最速を生み出すキャッシュの基本形です。
stages:
- build
すべてのジョブで共通のキャッシュ設定を定義
default:
cache:
# ブランチやジョブごとにキャッシュを分離しつつ、同じブランチなら共有するキー
key: ${CI_COMMIT_REF_SLUG}
paths:
- .npm/ # npmのキャッシュディレクトリを指定
- node_modules/ # モジュール自体もキャッシュ
build_project:
stage: build
image: node:18-alpine
script:
# キャッシュを活用してnpm installを高速化
- npm ci –cache .npm –prefer-offline
- npm run build
💡 ここがエンジニアのこだわりポイント!
1. `key` の設計: `${CI_COMMIT_REF_SLUG}` を使うことで、機能ブランチごとに独立したキャッシュを持ちつつ、同じブランチ内では前のビルドのキャッシュを使い回せます。
2. npmのキャッシュ戦略: 単に `node_modules/` をキャッシュするだけでなく、npm自身のキャッシュディレクトリ(`.npm/`)も同時に保持することで、`npm ci` のネットワーク負荷を極限まで下げています。
—
3. ジョブをつなぐ「アーティファクト」の正しい作法
次に、ビルドした成果物を次のステージ(テストやデプロイ)に渡すための「アーティファクト」です。
よくある誤りが、「すべてのファイルをキャッシュやアーティファクトに突っ込む」という力技です。これはGitLabサーバーのストレージを圧迫し、ネットワーク転送のボトルネックになります。
stages:
- build
- deploy
build_app:
stage: build
image: node:18-alpine
script:
- npm ci
- npm run build
artifacts:
name: “webapp-dist-${CI_COMMIT_SHORT_SHA}” # アーティファクトに分かりやすい名前をつける
paths:
- dist/ # ビルド成果物が入ったディレクトリだけを指定!
expire_in: 7 days # 【超重要】不要になったら自動削除する期限
deploy_app:
stage: deploy
image: alpine:latest
script:
- echo “前のジョブから渡された dist/ をデプロイします”
# デプロイ処理…
💡 ここがエンジニアのこだわりポイント!
- `expire_in`(有効期限)を必ず設定する: デフォルトのままだと、過去のすべてのビルド成果物がGitLabサーバーに永遠に残り続け、ストレージ容量を爆発させます。「7 days」や「30 days」など、チームの運用に合わせた適切な有効期限を設定するのがプロの作法です。
—
4. 【実践】キャッシュとアーティファクトを組み合わせた最強のHelloWorld
それでは、ここまでの知識を統合して、無駄を削ぎ落とした「最速のパイプライン」を構築してみましょう。シンプルなWebアプリのビルドを想定した設定ファイルです。
パイプラインのステージ定義
stages:
- install
- build
- test
variables:
# npmのログ出力を抑制してパフォーマンス微増を狙う
npm_config_loglevel: “warn”
— キャッシュのグローバル定義 —
cache: &global_cache
key:
files:
- package-lock.json # package-lock.jsonが変更された時だけキャッシュを無効化する神機能!
paths:
- .npm/
policy: pull-fetch
1. 依存関係をインストールするジョブ(キャッシュを書き込む)
install_dependencies:
stage: install
image: node:18-alpine
script:
- npm ci –cache .npm –prefer-offline
cache:
<<: global_cache
policy: pull-push # このジョブだけはキャッシュを「保存(push)」する権限を持つ
2. ビルドを行うジョブ(キャッシュを読み込み、成果物をアーティファクトにする)
build_application:
stage: build
image: node:18-alpine
script:
- npm run build
artifacts:
name: build-artifact
paths:
- dist/
expire_in: 1 days # 短命に設定してストレージを節約
3. テストを行うジョブ(ビルド成果物をアーティファクト経由で受け取る)
run_tests:
stage: test
image: node:18-alpine
script:
- echo “dist/ フォルダの中身を確認してテストを実行します”
- ls -la dist/
- npm test
🔥 この設定の最高なポイント
- `key: files: [package-lock.json]`: これがGitLab CI/CDの隠し味(強力な機能)です。依存関係(`package.json`等)に変更がない限り、前回のキャッシュが完璧に再利用されます。無駄なキャッシュの無効化が起きません。
- `policy` の使い分け: インストールジョブだけに `pull-push` を許可し、ビルドやテストジョブは `pull-fetch`(読み込み専用)にすることで、キャッシュの競合や無駄な上書きを防ぎ、パイプラインの安定性と速度を最大化しています。
—
スコープを明確にし、キャッシュとアーティファクトを適切に使い分けることで、あなたのGitLab CI/CDパイプラインは見違えるほど軽快に動き出します。
「これを設定したおかげで、今日のコーヒーブレイクが待ち遠しくなくなったよ」――そんな風にチームから感謝されるエンジニアに、今日からなってみませんか?
明日からの快適な開発ライフを、心から応援しています!