vagrant+chef-soloでRails用のruby環境作る

前回chef入門してたらやたら長くなったので、やっと本題のchefでrails用のruby環境作るのやった。
なんか色々試行錯誤しながらも出来たのでまとめた。

  • 準備

手元の環境はMacOSX10.10(Yosemite)です。rubyはrvmで2.2.0入れてる。

VirtualBox入ってなければインストールしてください。現時点の最新版は4.3.20です。
https://www.virtualbox.org/wiki/Downloads

Vagrantも入ってなければインストールしてください。現時点の最新版は1.7.2です。
https://www.vagrantup.com/downloads.html
※前回のエントリでリンクが間違ってて微妙に古いバージョンだったので元記事も追記しておきました。

vagrant-omnibusプラグインというのを使うので、これも入れてください。

$ vagrant plugin install vagrant-omnibus

あとchef関連のツールをgemで入れる。bundleしようかと思ったけど、Vagrantfileが置かれてるディレクトリにそのままアプリも置いて開発したくてGemfileは純粋なアプリケーションだけにしたかったのでchef周りのツールは普通に自分で入れる。

$ gem install chef
$ gem install knife-solo
$ gem install berkshelf
  • VMの設定する

まず、新しいVagrantfile作る。元ネタは前回同様CentOS6.5のイメージです。

$ mkdir chef-rails
$ cd chef-rails/
$ vagrant init opscode-centos-6.5 http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5_chef-provisionerless.box

Vagrantfileができるので、中身はこんなかんじに設定しておく。

# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "opscode-centos-6.5"
  config.vm.box_url = "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5_chef-provisionerless.box"

  config.vm.network :"forwarded_port", guest: 3000, host: 3000
  config.vm.network "private_network", ip: "192.168.33.10"
  config.vm.provider "virtualbox" do |vb|
    vb.customize ["modifyvm", :id, "--memory", "1024"]
  end

  config.omnibus.chef_version = :latest

  config.vm.provision :chef_solo do |chef|

    chef.cookbooks_path = "./cookbooks"
    chef.run_list = [
    ]
    chef.add_recipe 'build-essential'
    chef.add_recipe 'git'
    chef.add_recipe 'rvm::system'
    chef.add_recipe 'sqlite'

    chef.json = {
      rvm: {
        user: "vagrant",
        default_ruby: "ruby-2.2",
        rubies: ["ruby-2.2" ]
      }
    }
  end
end

ポイントはネットワークとメモリ周りの設定いじってるのと、起動時にchef入れてそのままクックブック適用までやってる。
とりあえず最小限でsqlite入れてるけど、mysqlとかnginxとか入れたくなったら随時足していればよいんじゃないかと。
Vagrantfileとクックブック分けようかと思ったけど、Vagranfileのファイル共有機能でVagrantfileあるディレクトリでそのままアプリ開発したかったので、ここにchefの設定ファイル一式のディレクトリ体系掘るとカオスなかんじになる。小規模な開発用途なら直接Vagrantfileにchefも書いてしまった方がコンパクトにまとまってよいかなぁと。もっと大規模になると、そもそもchefと純粋なアプリは別のディレクトリで管理した方がよいんじゃないかと思う。

  • クックブックを集める

ところでまだ必要なクックブックが手元にないので、Berksfileというファイルを作って、こんなかんじで書いておく。

source "https://supermarket.chef.io"

cookbook 'build-essential', '~>2.1.3'
cookbook 'git', '~>4.1.0'
cookbook 'rvm', '~>0.9.2'
cookbook 'sqlite', '~>1.1.0'

クックブックを取得して配置する。

$ berks vendor cookbooks

ググるとberks install --path cookbooksと書いてる記事が多いけど、既に非推奨のようです。

  • VM起動して料理する

準備出来たのでVMを起動する。もろもろダウンロードしてインストールするので結構時間かかりますので気長に待ちましょう。

$ vagrant up

インストール終わったら確認。

$ vagrant ssh
Last login: Sat Jan 31 03:48:57 2015 from 10.0.2.2
[vagrant@localhost ~]$ ruby -v
ruby 2.2.0p0 (2014-12-25 revision 49005) [x86_64-linux]
exit

webappでsshできるように名前つけておく。例は単純追記ですが、前回と同じ名前なのでよしなに上書きするなりマージしてください。

$ vagrant ssh-config --host webapp >> ~/.ssh/config
$ ssh webapp
Last login: Sat Jan 31 04:03:46 2015 from 10.0.2.2
[vagrant@localhost ~]$ exit

VagrantfileがあるディレクトリがVM側の/vagrantにマウントされるのでここの配下でそのまま開発すれば手元で好きなエディタが使える。
Vagrantfileがあるディレクトリでrails入れる用のGemfileを作る。

$ bundle init

Gemfileの中身はとりあえずrailsだけ書いておく。

source 'https://rubygems.org'

gem 'rails', '4.2.0'

bundleはVMの中で実行する。権限の問題で、インストール先のパスを明示的に指定してる。rvmのクックブックの設定でなんかうまい回避方法ありそうなんだけど、rvmのクックブックsystemじゃなくてuserとかにしてみてもsystemパスにインストールされてちょっとよくわからんかったです。

$ ssh webap
$ cd /vagrant
[vagrant@localhost vagrant]$ bundle install --path vendor/bundle

インストール終わったらrails newする。Gemfile上書いてよいか確認がでるのでYで上書く。

[vagrant@localhost vagrant]$ bundle exec rails new .
       exist
      create  README.rdoc
      create  Rakefile
      create  config.ru
      create  .gitignore
    conflict  Gemfile
Overwrite /vagrant/Gemfile? (enter "h" for help) [Ynaqdh] Y

Gemfileの以下の行のコメントアウトを解除。nodejsとか入ってない場合はV8のjavascriptエンジン入れてくれるやつらしい。

gem 'therubyracer', platforms: :ruby

再度bundle実行。

[vagrant@localhost vagrant]$ bundle install --path vendor/bundle

Railsサーバ立ち上げる。Rails4.2からバインドするアドレス明示的に0.0.0.0でany指定しないと上手く動かんらしい。

$ bundle exec rails server -b 0.0.0.0
=> Booting WEBrick
=> Rails 4.2.0 application starting in development on http://0.0.0.0:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
[2015-01-31 05:03:28] INFO  WEBrick 1.3.1
[2015-01-31 05:03:28] INFO  ruby 2.2.0 (2014-12-25) [x86_64-linux]
[2015-01-31 05:03:28] INFO  WEBrick::HTTPServer#start: pid=16046 port=3000

手元のブラウザで以下のURLにアクセスしてWelcome画面が見えればOK。
http://192.168.33.10:3000

  • テンプレ使い方のメモ

今後のために完成したものをテンプレとして GitHubにあげておいた。
https://github.com/minamijoyo/chef-rails

新しいプロジェクトごとにgit cloneしてきて

$ git clone https://github.com/minamijoyo/chef-rails (project_name)
$ cd (project_name)
$ berks vendor cookbooks
$ vagrant up
$ vagrant ssh-config --host (hostname) >> ~/.ssh/config
$ ssh (hostname)
[vagrant@localhost ~]$ cd /vagrant
[vagrant@localhost vagrant]$ bundle install --path vendor/bundle
[vagrant@localhost vagrant]$ bundle exec rails new .
(Gemfileのtherubyracerのコメントアウト解除)
[vagrant@localhost vagrant]$ bundle install --path vendor/bundle
$ bundle exec rails server -b 0.0.0.0

というかんじでrails newできるようになってよいんじゃないかと。railsインストールするところまでテンプレに含めるか悩ましいところだけど、とりあえず汎用性考えて手前で寸止めしておいた方が何かと使い回ししやすそうな気がした。
最後のtherubyracerのところchefでnodejs入れておけば手間減りそうなので、次なにかパッケージ追加したくなったタイミングでついでにnodejsも入れよう。とりあえずいいかんじ開発環境できたので一旦これでおk。