Vagrant入門


# はじめに
[今更ですがChefとVagrantを勉強してみた](http://qiita.com/MasayaMizuhara/items/215e1e67605e39a1b820 "今更ですがChefとVagrantを勉強してみた")でChefとVagrantを使って仮想環境を構築する手法をまとめた。今回はVagrantについてもう少し真面目に勉強したのでその内容をまとめた。

# Vagrantとは
Vagrantとは簡単なコマンドで任意の構成の仮想マシンを自動的に構築してくれるツールのことで、Vagrantを使うと、

* 自分の好きなOSが動作する仮想マシンの生成
* その仮想マシンのRAM容量/CPU数などの物理的な属性値の変更
* 共有フォルダをセットアップし、ホスト・ゲストマシン間でのファイルの共有
* シェルスクリプトやプロビジョニングツール(ChefやPuppetなど)により仮想マシン上へのソフトウェアのプロビジョニング

などがコマンド一つで実現可能となる。Vagrantを使うと **開発に必要なソフトウェアのインストールや設定作業が自動化できる** (開発環境と実働環境の設定を揃えることができる)ため、開発環境では発生しないが実働環境で発生するバグを避けることができるなどのメリットがある。

# 環境構築
Vagrantを使用するための環境構築手順を紹介する。

## VirtualBoxのインストール
VirtualBoxとは、Oracleが提供しているクロスプラットフォームな仮想化ソフトウェアであり、[ここ](https://www.virtualbox.org/wiki/Downloads)からダウンロードできる。自分が使用しているOSのパッケージをダウンロードし、インストールする。
インストール後はコンピュータを再起動し、セットアップされたカーネルドライバを確実にクリーンな状態にすることが推奨されているので、再起動をする。

## Vagrantのインストール
[ここ](http://downloads.vagrantup.com/)からダウンロードし、インストーラの指示に従ってインストールを行う。
最新版は1.4系であるが、1.4系は頻繁にバージョンアップが続いている様なので、安定板である1.3系を使う方が良いと思う。

## SSHクライアントのインストール(Windowsユーザのみ)
Windowsユーザは [PuTTY](http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html) などのSSHクライアントをインストールする必要がある。
SSHログインの際に接続先などを聞かれるので、下記の通り設定する。

| 設定項目 | 設定値 |
|:------:|:------:|
| 接続先  |127.0.0.1 |
| ポート  |     2222 |
| ID     |  vagrant |
| PW     |  vagrant |

# Vagrantを使ってみる
Vagrantを使える環境が整ったので実際に使ってみよう。

## 起動
http://cloud-images.ubuntu.com/vagrant/saucy/current/saucy-server-cloudimg-amd64-vagrant-disk1.box という **box** を使用してubuntu1310という名前の仮想環境を起動するには、下記コマンドを実行すれば良い。boxとは利用したいOSイメージのことで、[ここ](http://www.vagrantbox.es/)から自分の好きなboxを選択することができる。boxに付ける名前(下記サンプルではubuntu1310)も自分の好きな名前を付けることができる。

```
 $ vagrant init ubuntu1310 http://cloud-images.ubuntu.com/vagrant/saucy/current/saucy-server-cloudimg-amd64-vagrant-disk1.box
```

boxの取得が完了したら、下記コマンドを入力して仮想環境を起動する。

```
 $ vagrant up
```

### 補足

* ``` vagrant init ``` コマンドを打つのはboxを取得する初回のみで、次回以降は ``` vagrant up ``` と入力するだけで良い。
* Vagrantはboxをグローバルに管理する。つまり、一つのboxを複数のプロジェクトから利用することができる。Vagrantはboxをクローン元のベースイメージとして使うだけなので変更が衝突することは無い。

## 仮想環境へSSHログイン
下記コマンドで今起動した仮想環境にSSHログインしてみよう。

``` 
 $ vagrant ssh
``` 

ソフトウェアのインストールやファイルの編集など、自分の好きなことができるので、遊んでみましょう。

## 仮想マシンの停止/削除
飽きたら ``` exit ``` と入力してホストマシンのターミナルに戻り、下記コマンドで仮想マシンを停止する。

``` 
 $ vagrant halt
``` 

仮想マシンが完全に不要になった場合は下記コマンドで削除する。

``` 
 $ vagrant destroy
``` 

以上の様に、Vagrantを使うことで仮想環境の構築やら削除やらを非常に簡単に行うことができる。

# Vagrantfileの編集
Vagrantfileを編集することで、仮想マシン上で立ち上げたサーバへのアクセスや仮想マシンへ特定のプロビジョニングを実行することなどが可能となる。Vagrantfileを編集する前に、Vagrantfileとは何かについて説明をする。

## Vagrantfileとは
Vagrantfileとは、ブートするOSなど作業環境を生成するために必要な情報が記載されたファイルであり、プロジェクト毎に一つのVagrantfileを持つ。 ``` vagrant init ``` により生成されるVagrantfileにはネットワーク設定などいろいろ書かれて入るが、最小構成は下記の様になる(と思う)。

```Vagranfile
1 VAGRANTFILE_API_VERSION = "2"
2 Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
3   config.vm.box = "ubuntu1310"
4 end
``` 

上記Vagrantfileは、

* 1行目でV2設定の採用(VAGRANTFILE_API_VERSION = "2")を宣言しており、
* 2〜4行目で基本的な設定値を変数に代入(今回はconfig.vm.boxという変数名にubuntu1310という値を代入)する

という処理を行っている。

### 補足：V2設定とは
VagrantにはV1とV2と呼ばれる、二つの設定バージョンがある。Vagrantの初めての安定板リリースである1.x系から使える設定構文がV1、Vagrant2.0になる予定の設定構文がV2である。V2設定は実験的なもので2.0の完成に至るまで活発に変更が加えられるらしいが、1.2系や1.3系が主流になるにつれ、V2設定の利用が増えている模様。
ちなみに、V1設定のVagrantfileは下記の様になっており、

```Vagranfile
Vagrant::Config.run do |config|
  # 何らかの設定
end
``` 

また、下記の様に一つのVagrantfileにV1・V2設定を混在させることも可能。

```Vagranfile
Vagrant::Config.run do |config|
  # V1の設定
end

Vagrant.configure("2") do |config|
  # V2の設定
end
```

## ネットワークの設定
Vagrantを使うと、ゲストマシンに静的なIPを割当て、ホストとゲストだけからなるプライベートなネットワークを構築することが簡単にできる。下記の様にVagrantfileを編集(下記4行目を追加)するだけで、仮想マシン上で起動しているWebサーバにアクセスできる。

```Vagranfile
1 VAGRANTFILE_API_VERSION = "2"
2 Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
3   config.vm.box = "ubuntu1310"
4   config.vm.network :private_network, ip: "192.168.33.10"
5 end
``` 

Vagrantでネットワークの設定を行う方法としては他にも、フォワードされたポートの使用やブリッジのネットワークの使用などがあり、それぞれメリット/デメリットがある様なので、興味のある方は調べてみると良いと思う。

## プロビジョニング
``` vagrant up ``` により得られる仮想環境は必要最小限の構成であり、開発を行うのに必要なソフト(例えばgitなど)が入っていない。仮想環境構築時に開発に必要なソフトも自動でインストールしてくれたら便利でしょう。これを行うのが、プロビジョングである。プロビジョニング手法には大きく分けて **シェルスクリプトの利用** と **プロビジョニングツール(ChefやPuppet)の利用** の2通りがある。今回はシェルスクリプトの利用によりgitとnvmとnodeをUbuntu13.10にインストールする例を紹介する。

#### 1.シェルスクリプトの作成
手動でgitとnvmとnodeをインストールする際に入力するコマンドを記載したシェルスクリプト(provision_root.shとprovision_node.sh)を作業ディレクトリ(Vagrantfileがある場所)に作成する。
もしサイレントモードで実行したいのであれば、 ``` apt-get update > /dev/null 2>&1 ``` の様に各コマンドの最後に ``` > /dev/null 2>&1 ``` を追加する。

```provision_root.sh
echo "Updating package."
apt-get update

echo "Installing git."
apt-get install -y git
``` 

```provision_node.sh
echo "Installing nvm and node."
git clone https://github.com/creationix/nvm.git /home/vagrant/.nvm
source /home/vagrant/.nvm/nvm.sh
nvm install v0.10
nvm alias default v0.10
echo "source /home/vagrant/.nvm/nvm.sh" >> /home/vagrant/.bashrc
``` 

#### 2. Vagrantfileの編集
Vagrantfileを下記の様に編集する(5, 6行目を追加)。

```Vagranfile
1 VAGRANTFILE_API_VERSION = "2"
2 Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
3   config.vm.box = "ubuntu1310"
4   config.vm.network :private_network, ip: "192.168.33.10"
5   config.vm.provision "shell", path: "provision_root.sh"
6   config.vm.provision "shell", path: "provision_node.sh", :privileged => false
7 end
```

新規追加分のコードが行っている処理は、

* provision_root.shというパスにあるシェルスクリプトを使って仮想マシンのプロビジョニングをroot権限で行い(5行目)、
* provision_node.shというパスにあるシェルスクリプトを使って仮想マシンのプロビジョニングをvagrantユーザで行う(6行目)

という内容である。デフォルトだとシェルスクリプトの実行はroot権限で実行されるため、プロビジョニング中に生成されたファイルの権限はroot権限となってしまう。そのためprovision_node.shのプロビジョニングはvagrantユーザで行う様に変更している(変更しないと、例えば ``` npm install -g underscore ``` などとした場合にエラーとなる)。

#### 3. 仮想環境の起動
``` vagrant up ``` で仮想マシンを起動し、起動後 ``` vagrant ssh ``` で仮想マシンにSSHログインする。ログイン後ターミナルに ``` node -v ``` と打つとnodeがインストールされていることが確認できる。

## ボックスの作成
シェルスクリプトやChefなどを使うことで任意の構成の仮想マシンを構築できるとは言え、仮想マシンを新規作成する度にシェルスクリプトやChefを実行するのは煩わしい。そこで、ベースとなったboxにソフトをインストールしたboxを新規boxとして作成する方法を紹介する。

ここまで記事を読んでくれたのであれば、nodeがインストールされたUbuntu13.10の仮想環境が手元のPCにあると思う。今回はこれを新規boxとして作成することにする。

#### 1. 作業ディレクトリに移動
作業ディレクトリ(Vagrantfileがあるディレクトリ)に移動する。

#### 2. 既存のVagrant環境を再利用可能なboxにパッケージ化
``` vagrant package ``` と入力する。暫くするとpackage.boxが生成される。

#### 3. boxの追加
下記コマンドでboxを一覧に追加する。customized_ubuntu1310の部分はboxに付ける名前であり、任意の名前を付けることができる。

``` 
 $ vagrant box add customized_ubuntu1310 package.box
``` 

今回追加したboxを使用したい場合は ``` vagrant init customized_ubuntu1310 ``` に続けて ``` vagrant up ``` とすれば良い。