複数バージョンのbundlerがインストールされている時の挙動おぼえがき

概要

複数バージョンのbundlerがインストールされているとき、どれが選択されるのか曖昧だったので実験

注意

公式ドキュメントの記述がみあたらなかったので、バージョンが変わると挙動が変わるかもしれないです

環境

ruby:3.0.1-alpine を使用。defaultで入っているbundlerは、2.2.15です

docker run --rm --name ruby -it ruby:3.0.1-alpine /bin/sh
/ # gem list --local | grep bundler
bundler (default: 2.2.15)
/ # bundler -v
Bundler version 2.2.15

先に結論

以下の優先順でバージョンが選ばれるようです。default は関係ない様子

  1. $BUNDLER_VERSION
  2. Gemfile.lock の BUNDLED WITH
  3. 一番新しいバージョン

複数バージョンを入れた場合、default や、インストール順は左右されず、最新のバージョンが参照される

/ # gem install bundler:2.2.20
Fetching bundler-2.2.20.gem
Successfully installed bundler-2.2.20
1 gem installed

/ # gem install bundler:2.2.19
Fetching bundler-2.2.19.gem
Successfully installed bundler-2.2.19
1 gem installed

/ # gem list --local | grep bundle
bundler (2.2.20, 2.2.19, default: 2.2.15)

/ # bundle -v
Bundler version 2.2.20

ディレクトリに Gemfile.lock がある場合、そこの BUNDLED WITH にかかれているバージョンが参照される

/ # cat <<EOS > Gemfile.lock
> GEM
>   remote: https://rubygems.org/
>   specs:
>     rack (2.0.6)
> 
> PLATFORMS
>   ruby
> 
> DEPENDENCIES
>   rack
> 
> BUNDLED WITH
>   2.2.19
> EOS
/ # bundle -v
Bundler version 2.2.20

環境変数 BUNDLER_VERSION があると、それが最優先される

/ # export BUNDLER_VERSION=2.2.15

/ # bundle -v
Bundler version 2.2.15

環境変数 BUNDLER_VERSION や、Gemfile.lock に書かれたバージョンがインストールされていな場合、最新のバージョンが参照される

bundle install しない限り、特に警告は出ませんでした

/ # export BUNDLER_VERSION=2.2.13

/ # cat <<EOS > Gemfile.lock
> GEM
>   remote: https://rubygems.org/
>   specs:
>     rack (2.0.6)
>
> PLATFORMS
>   ruby
>
> DEPENDENCIES
>   rack
>
> BUNDLED WITH
>   2.2.16
> EOS

/ # bundle -v
Bundler version 2.2.20

おまけ: bundle _version_ でバージョンを明示的に指定すると、そのバージョンが参照される

/ # bundle _2.2.15_ -v
Bundler version 2.2.15

存在しないバージョンを指定すると怒られます

/ # bundle _2.2.00_ -v
/usr/local/lib/ruby/3.0.0/rubygems.rb:281:in `find_spec_for_exe': can't find gem bundler (= 2.2.00) with executable bundle (Gem::GemNotFoundException)
        from /usr/local/lib/ruby/3.0.0/rubygems.rb:300:in `activate_bin_path'
        from /usr/local/bundle/bin/bundle:23:in `<main>'

古い ruby image だと、挙動が変わります

docker run --rm --name ruby -it ruby:2.5.1-alpine /bin/sh
/ # gem list --local | grep bundler
bundler (1.16.6, default: 1.16.2)
/ # bundler -v
Bundler version 1.16.6

2.2.20 をインストールしても、1.16.6 が参照されたまま

/ # gem install bundler:2.2.20
/ # gem list --local | grep bundler
bundler (2.2.20, 1.16.6, default: 1.16.2)
/ # bundler -v
Bundler version 1.16.6

これは、古い ruby の Dockerfile の中で BUNDLER_VERSION が設定されているため そのため、BUNDLER_VERSION を unset しないと想定通りの挙動してくれない

こちらのissueで議題になって、新しいバージョンでは BUNDLER_VERSION がセットされないようになっています

github.com