Mac で Ruby on Rails 開発用の CentOS7 仮想サーバを構築する (VirtualBox, Vagrant, Chef-solo, Berkshelf)


## 仮想サーバに開発環境を作ろうと思った理由
* Mac 自身にセットアップしてもいいのだけれど、色々インストールしたりしていると不要なものが溜まり続けて肥大化しそう
* なのでさっと捨てられてさっと作り直せる環境がよい
* マシンを乗り換えても環境構築が楽にできる
* Vagrant とか Chef を使ってみたかった

## 環境
### ホスト OS
* OS X 10.9.5
	* 諸々のインストールが楽なので [Homebrew](http://brew.sh/) を使用する
		* Homebrew の拡張 [Homebrew-Cask](http://caskroom.io/) も使う
			* 以下手順はこれらのインストールが既にされている前提

### ゲスト OS
* CentOS 7
	* net-tools が標準で入らなくなったらしいので、netstat や ifconfig などが使えなくてあせった・・・

## セットアップしたもの
### ホスト OS
* VirtualBox (4.3.16)
	* 仮想マシンを作るもの
		* 無料で使えるのが素晴らしい

* Ruby
	* rbenv (0.4.0)
		* Ruby のバージョンが管理できる
	* ruby-build (20140919)
		* rbenv で各バージョンの Ruby をインストールする際に必要
	* Ruby (2.1.3)
		* rbenv を使用してインストールする
 	* Bundler (1.7.3)
		* Vagrant のプラグインインストール時に使った(はず)
		* Vagrant のプラグインを使わないのであれば、Ruby 周りは必要ないかも

* Vagrant
	* Vagrant (1.6.5)
		* 仮想環境の構築/管理が楽にできる優れもの
		* 最近のバージョンだと Docker も使えるらしい
	* vagrant-omnibus (1.4.1)
		* ゲスト OS を色々と設定する際には後述の Chef を使用するのだが、ゲスト OS に Chef 関係が入っていない場合インストールしてくれる

* Chef-Solo
	* ChefDK (0.2.2)
		* インフラ構築を自動化する Chef 周り一式が揃っているもの
			* 別々に入れると各種依存関係でうまく動かなかったりするのでこれを入れるのが吉
	* Knife-solo (11.16.0)
		* ゲスト OS 設定用ファイルの転送やら設定実行やらをやってくれるもの
	* Berkshelf (3.1.5)
		* ChefDK に最初から含まれている
		* 既に作成されてあるレシピ群を使用するための管理ツール


### ゲスト OS
* CentOS (7.0)
* Ruby
	* rbenv (0.4.0)
	* ruby-build (0.8.0)
	* Ruby (2.1.3)
	* bundler (1.7.3)
	* rails (4.1.6)
* Sqlite (1.1.0)


## ホスト OS セットアップ (Mac)
### Homebrew + Cask でセットアップする
* VirtualBox

VirtualBox をインストールする

```
$ brew cask install virtualbox
```

* Ruby

rbenv, ruby-build をインストールする

```
$ brew install rbenv ruby-build
```

rbenv の設定を入れる(下記は bash の場合)

```
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source .bash_profile
```

rbenv でインストールできる Ruby のバージョンを確認する

```
$ rbenv install -l
```

rbenv で Ruby をインストールする (下記は 2.1.3 の場合)

```
$ rbenv install 2.1.3
```

システムが使用する Ruby のバージョンを上記でインストールしたものにする

```
$ rbenv global 2.1.3
```

Bundler をインストールする

```
$ gem install bundler
```

* Vagrant

Vagrant をインストールする

```
$ brew cask install vagrant
```

vagrant-omnibus をインストールする

```
$ vagrant plugin install vagrant-omnibus
```

* Chef-Solo

ChefDK をインストールする

```
$ brew cask install chefdk
```

パス設定を追加する (シェルの環境設定ファイルに追加する 追加後の再読込を忘れずに)

```
PATH=$HOME/.chefdk/gem/ruby/2.1.0/bin:/opt/chefdk/bin:$PATH
```

knife-solo をインストールする

```
$ chef gem install knife-solo
```

knife の初期設定をする (デフォルト設定で問題無し)

```
$ knife configure
```

## Vagrant の設定をする

* Box (セットアップする仮想 OS のイメージ)を追加する
	* 今回は下記 URL で提供されているものを使用した (CentOS7.0 x86_64 minimal (VirtualBoxGuestAddtions 4.3.14))
		* http://www.vagrantbox.es/
	* 「centos70_64」はラベルなのでお好みで

```
$ vagrant box add centos70_64 https://f0fff3908f081cb6461b407be80daf97f07ac418.googledrive.com/host/0BwtuV7VyVTSkUG1PM3pCeDJ4dVE/centos7.box
```

* 仮想マシンを作成する(ディレクトリ名はお好みで)

仮想マシン用ディレクトリを作成する
Vagrant の設定ファイルひな形(Vagrantfile)を作成する

```
$ mkdir -p ~/vagrant/centos70_64
$ cd ~/vagrant/centos70_64
$ vagrant init centos70_64
```
Vagrantfile を編集する (Vagrant init しないでイチから書いてもよい)

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

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
    config.vm.box = "centos70_64" # 追加した Box 名
    config.vm.network :private_network, ip: "192.168.200.101" # ゲスト OS の IP アドレスを明示したい場合
    config.omnibus.chef_version = :latest

    config.vm.provision "chef_solo" do |chef|
        chef.cookbooks_path = ["./chef-repo/cookbooks", "./chef-repo/site-cookbooks"]
        chef.json = { #
            rbenv: {
                rubies: ["2.1.3"],
                global: "2.1.3",
                gems: {
                    "2.1.3" => [
                        name: "bundler",
                        name: "rails",
                    ]
                }
            },
        }
        chef.run_list = [
            "ruby_build",
            "rbenv::system",
            "sqlite",
        ]
    end
end
```

## Chef-Solo の設定をする

* Chef-Solo の初期設定をする

各種設定ファイルのひな形を作成する (ディレクトリ名はお好みで)

```
$ knife solo init chef-repo
$ cd chef-repo 
```

* Berkshelf の設定をする

Berksfile を編集する

```txt:Berksfile
source "https://supermarket.getchef.com"
cookbook 'rbenv', github: "fnichol/chef-rbenv"
cookbook 'ruby_build'
cookbook 'sqlite'
```

Berksfile に記述した cookbook を取得する

```
$ rm -rf cookbooks; berks vendor cookbooks
```

## Vagrant を実行して仮想マシンを起動する

* 仮想マシンを起動する

```
$ vagrant up
```

本来はこれで全部のセットアップが完了するはずだが、共有領域がマウントできないと言われて途中で止まってしまった (仮想 OS 起動は出来ている)

```
==> default: Mounting shared folders...
    default: /vagrant => /Users/ikageso/vagrant/centos70_64
Vagrant::Errors::LinuxMountFailed: Failed to mount folders in Linux guest.
```

VirtualBox の guest addition がうまいことセットアップされていないようなので、手動で再セットアップをする (使用する VirtualBox のバージョンによっては上記エラーは出ないかも)

```
$ vagrant ssh -c 'sudo /etc/init.d/vboxadd setup'
```

Vagrant の reload と provison を実行する

```
$ vagrant reload
$ vagrant provision
```

特にエラーが発生しなければ完了！

## 仮想サーバにログインしてセットアップが完了しているか確認する

仮想サーバにログインする(Vagrantfile があるディレクトリで実行)

```
$ vagrant ssh
```

セットアップされたものを確認する

```
$ rbenv -v
$ ruby -v
$ bundle -v
$ rails -v
$ sqlite3 -version
```

## 今回仮想環境を作ってみて困った点
そんなに古くない技術者ブログの情報等を元に環境を構築しようとしたが、
各プロダクトの開発等が活発なのでバージョン周りでうまく動かなかったりしたので少し試行錯誤が必要だった。
やはり公式情報を参考にしたほうが最終的には手数が少なくなりそう。

## おまけ 仮想サーバの停止と破棄
仮想サーバを停止する

```
$ vagrant suspend
```

仮想サーバを破棄する

```
$ vagrant destroy
```