コンテンツへスキップ
LatchkeyLatchkey home

Bundler vs RubyGems: CI で Ruby の依存関係はどう機能するか

これらは実際にはライバルではありません。RubyGems は gem を install し、Bundler はそれらを固定して解決します。そして CI ではほぼ常に Bundler を上に載せたいはずです。

RubyGems は Ruby のパッケージマネージャであり registry クライアントです(gem install)。Bundler はその上に載り、Gemfile から一貫した gem の集合を解決し、再現可能な install のために Gemfile.lock に固定します。

RubyGemsBundler
役割個々の gem を install依存関係の集合を解決 + ロック
LockfileなしGemfile.lock
再現可能な install手動で固定した場合のみあり (lock から)
CI コマンドgem install <gem>bundle install / bundle ci
関係基盤となる層RubyGems の上に構築

CI において

アプリケーションでは Bundler を使いたいはずです。Gemfile.lock を commit し、bundle install(--deployment / frozen 設定つき)を実行して、すべてのパイプラインが同一の gem バージョンを得るようにします。素の gem install は job 内でスタンドアロンな CLI ツールを install するには問題ありませんが、再現可能なプロジェクト環境は得られません。Bundler は内部で RubyGems を使っており、競合するのではなく協調します。

gem を cache する

vendor/bundle(または gem)ディレクトリを Gemfile.lock でキーづけして cache し、bundle path を設定して install が再取得ではなく復元されるようにします。どの Ruby バージョンを対象にしても install は CI runner 上で実行され、ネイティブ gem のコンパイルが支配的な場合はより高速なマネージド runner が役立ちます。

Decide with your own numbers, not a feature table

Feature comparisons age badly and rarely decide anything, because both tools in a mature category can do the job. What differs is how each behaves on your repository, and that takes one afternoon to measure.

Terminal
# time a cold install with each candidate, cache cleared
hyperfine --prepare "rm -rf node_modules" --warmup 1 \
  "<tool-a> install" "<tool-b> install"

# and the thing CI actually pays for: a cold run with no local cache
docker run --rm -v "$(pwd):/w" -w /w node:22 sh -c "<tool> install"

What actually changes when you switch

  • Lockfile format. A switch is a one-way door for anyone still on the old tool until everyone migrates, so plan it as a single coordinated change.
  • Resolution strictness. Tools differ on whether an undeclared transitive import works, and the stricter one will surface latent bugs as new failures.
  • CI cache configuration. The cache path and key differ per tool; carrying over the old ones silently disables caching.
  • Everyone on the team and every runner must move together. Pin the version so they cannot drift.

結論

Ruby アプリを構築するなら、再現可能な install のために commit した Gemfile.lock とともに Bundler を使ってください。job 内でスタンドアロンなツールが必要なだけなら gem install で十分です。これらは層であって代替ではありません。Bundler がプロジェクトにとって正しいデフォルトです。

よくある質問

Bundler vs RubyGems: How Ruby Dependencies Work in CI?
RubyGems is Ruby's package manager and registry client (gem install). Bundler sits on top, resolving a consistent set of gems from a Gemfile and locking them in Gemfile.lock for reproducible installs.
In CI?
For applications you want Bundler: commit Gemfile.lock and run bundle install (with --deployment / frozen settings) so every pipeline gets identical gem versions. Bare gem install is fine for installing standalone CLI tools in a job, but it does not give you a reproducible project environment.
Cache the gems?
Cache the vendor/bundle (or gem) directory keyed on Gemfile.lock and set bundle path so installs are restored, not refetched. Whichever Ruby version you target, the install runs on CI runners; faster managed runners help when native gem compiles dominate.
Which should I choose?
Building a Ruby app: use Bundler with a committed Gemfile.lock for reproducible installs. Just need a standalone tool in a job: gem install is enough. They are layers, not alternatives - Bundler is the right default for projects.

関連ガイド