Macにサーバと同じ環境を構築する 〜Vagrant編〜

# はじめに

この記事では、クライアントPCにサーバと同じ環境を構築して開発をすすめられるようにするために、Vagrant（ヴェイグラント）というツールを使って環境を構築する方法を説明します。

# Vagrantについて

## なぜ使うのか
Vagrantを使うと以下のようなことができます。

- 自分のPCにサーバと同じ環境をコマンド1つで構築することができます。
- それをチームのメンバーや外注先のプログラマに配布して、全員が同じ環境で開発をすすめることができます。
- 開発が終わり使わなくなったら破棄して、必要になったらまた作ることも可能です。

## Vagrantとは

Vagrantはかんたんなコマンドで自動的に開発環境を構築することができるコマンドラインツールです。サーバの仮想化にはVirtualBoxなどの仮想化ソフトウェアを利用します。

例えば以下の2行であなたのMacの中にLinuxサーバができあがります。

```console
$ vagrant init hashicorp/precise32
$ vagrant up
```

## Vagrantfileについて

Vagrantの設定情報は`Vagrantfile` という1つのファイルに記述されるため、このファイルを配布・共有するだけで、みんなが同じ環境で開発できるようになります。

# インストール

## VirtualBoxのインストール

まず、Vagrantから利用するVirtualBoxをインストールします。

https://www.virtualbox.org/wiki/Downloads
ここからお使いの環境に合ったものをダウンロードしてインストールしてください。

## Vagrantのインストール

次にVagrantをインストールします。

http://www.vagrantup.com/downloads
ここからお使いの環境に合ったものをダウンロードしてインストールしてください。

インストール完了後、下記のコマンドが動作していればOKです。

```console:バージョン確認
$ vagrant -v
```

# 仮想サーバの起動手順

## ディレクトリを作成する

プロジェクト用に適当なディレクトリを用意してください。

```console:ディレクトリを作成し移動
$ mkdir sample
$ cd sample
```

## Boxを追加する

仮想サーバを構築するために、BoxファイルというVagrant用のOSイメージファイルを追加します。

https://github.com/rafacas/vagrant-boxes
今回はこの方のBoxを使わせてもらいます。
※Boxの追加方法にはいくつかあるようです

```console:Boxに追加
$ vagrant box add https://atlas.hashicorp.com/rafacas/centos62-plain
```

ダウンロードに1時間ぐらいかかります。

## 仮想サーバを起動する

```console
$ vagrant init rafacas/centos62-plain
$ vagrant up
```

完了したら起動しているか確認してみましょう。

```console:ステータス確認
$ vagrant status
Current machine states:

default                   running (virtualbox)
```


# 設定の変更

ここからはプロジェクトのサーバ要件に合わせて仮想サーバの設定を変更していきます。
作業としては `Vagrantfile` を編集するだけです。

## 基本的な設定

- 下記の設定をするとローカルPCの8080番ポートを仮想サーバの80番ポートにフォワードします。

```ruby:Vagrantfile
# config.vm.network "forwarded_port", guest: 80, host: 8080
↓
config.vm.network "forwarded_port", guest: 80, host: 8080
```

- 下記の設定をすると `192.168.33.10` で仮想サーバにアクセスできるようになります。
※ローカルPCからのみアクセス可能です。

```ruby:Vagrantfile
# config.vm.network "private_network", ip: "192.168.33.10"
↓
config.vm.network "private_network", ip: "192.168.33.10"
```

- 以下の設定をすると、ローカルPCの `sample` ディレクトリが、仮想サーバの `/var/www/html` に同期します。
`sample` 配下のファイルを変更すると、それが即時にサーバに反映されるので便利です。

```ruby:Vagrantfile
# config.vm.synced_folder "../data", "/vagrant_data"
↓
config.vm.synced_folder ".", "/var/www/html",
    :owner => "vagrant",
    :group => "vagrant",
    :mount_options => ["dmode=777,fmode=777"]
```

設定を反映させるために仮想サーバを再起動します。

```console:仮想サーバの再起動
$ vagrant reload
```

## プロビジョニング

現在の状態では、仮想サーバにApacheやMySQLがインストールされていないので、これらのソフトをインストールをする必要があります。
Vagrantにはプロビジョニングの機能もあり、インストールなどの作業を自動化することが可能です。

以下では Apache、MySQL、PHP、Gitをインストールするように設定します。
（インストールするソフトのバージョン等も自由に選択可能です）

```ruby:Vagrantfile（追記）
  config.vm.provision "shell", inline: <<-SHELL
    yum -y update

    service iptables stop
    chkconfig iptables off

    # Apache
    yum -y install httpd
    service httpd start
    chkconfig httpd on

    # MySQL
    yum -y install mysql mysql-server mysql-devel
    service mysqld start
    chkconfig mysqld on

    # PHP
    yum -y install php php-opcache php-devel php-mbstring php-mcrypt php-mysqlnd php-phpunit-PHPUnit php-pecl-xdebug php-pecl-xhprof

    cp /etc/php.ini /etc/php.ini_org
    sed -i -e "s|expose_php = On|expose_php = Off|" /etc/php.ini
    sed -i -e "s|;date.timezone =|date.timezone = Asia/Tokyo|" /etc/php.ini
    sed -i -e "s|display_errors = Off|display_errors = On|" /etc/php.ini
    sed -i -e "s|;mbstring.language = Japanese|mbstring.language = Japanese|" /etc/php.ini

    service httpd restart

    # Git
    yum install -y git

  SHELL
```

プロビジョニングは最初の `vagrant up` の時にしか自動実行されないため、後から `Vagrantfile` を変更した場合は手動でプロビジョニングを行います。

```console:プロビジョニング
$ vagrant provision
```

※今回、プロビジョニングをシェルコマンドで行いましたが、ChefやAnsible等のプロビジョニングツールを使用可能です。

# 確認

ブラウザから
http://localhost:8080/
もしくは
http://192.168.33.10/
にアクセスして、Apacheのデフォルト画面が表示されれば成功です。

このあとは仮想サーバにSSHログインして設定を変更したり、sampleディレクトリにプログラムを作成したりしながら開発を進めます。


# その他のコマンド

```
# 起動
vagrant up

# シャットダウン
vagrant halt

# 破棄（中身が消えます）
vagrant destroy

# 再起動（halt -> up と同じ）
vagrant reload

# 状態の保ったままスリープ
vagrant suspend

# suspendから復帰
vagrant resume

# 仮想サーバにSSHログイン
vagrant ssh
```

次回は同じことをChefでやってみたいと思います。