できる気がしてきた。

僕の興味のあることを共有します。

Vagrantのprovisionでrbenvを使う

最近お仕事でrubyを使うことがあったのですが、 rubyはバージョンについてセンシティブであるので、 rbenvのようなバージョン管理ツールが必須です。

そこで、メンバー間で開発環境を共通化するためにVagrantfileを用いようと思い、 Vagrantfileを作っていたところシェルスクリプトでプロビジョニングしようとすると、 rbenvをインストールしてもプロビジョニング中はそのコマンドが使えないという奇妙な現象に陥りました。

どう言うことかというと

  config.vm.provision "shell", inline: <<-SHELL
    sudo apt-get update
    git clone https://github.com/rbenv/rbenv.git ~/.rbenv
    git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
    echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
    echo 'eval "$(rbenv init -)" >> ~/.bash_profile
    source ~/.bash_profile
  rbenv install 2.0.0-p247
    rbenv global 2.0.0-p247
  SHELL

が動かないのです。原因はいくつかありました。

  1. boxに使っていたubuntuでは、bashの設定ファイルは、~/.bash_profile ではなく、~/.bashrcであること
  2. vagrantのプロビジョニングで使われるbashはnon-itaractiveで起動しており、ubuntuの~/.bashrcでは、non-intaractiveモードでは~/.bashrcの処理を途中で切り上げてしまう設定になっていること
  3. vagrantのプロビジョニングはrootユーザーで実行されているのでホームディレクトリが/rootになっていること

これらを踏まえて、修正版はこうなりました。

  config.vm.provision "shell", privileged:false, inline: <<-SHELL
    set -i
    sudo apt-get update
    git clone https://github.com/rbenv/rbenv.git ~/.rbenv
    git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
    echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
    echo 'eval "$(rbenv init -)" >> ~/.bashrc
    source ~/.bashrc
    rbenv install 2.0.0-p247
    rbenv global 2.0.0-p247
  SHELL

set -iとは、どうやらbashインタラクティブモードに変更するコマンドです。

無事、vagrantでrbenvが使えるようになりました。めでたし。 まぁ、共通化を図るのであれば、本来はプロビジョニングツールを使わずにBoxを作るのが定石ですね :)