<Vagrant+VirtualBox>ローカルで仮想環境を立ち上げてみる

#VagrantとVirtualBoxの棲み分け

##VirtualBox
`VirtualBox`は、仮想環境を立ち上げる`VMware`、つまり、仮想マシンのソフトウェアの一種。
ホストOS（i.e. macのパソコン）と呼ばれるメインのOSにインストールされたアプリのように、**他OSを利用することができる（i.e. 仮想環境）**。

##Vagrant
`Vagrant`は、**仮想マシンの環境管理やビルドを自動化できるツール**で、簡単なコマンド一つで環境セットアップができるので、より製品開発に時間を費やせるようになる便利ソフト。Vagrantfile一つで、その設定ができて、共有も簡単なので、チーム開発にも有効。


##vagrant-hostsupdaterのプラグインを入れておくと便利
[vagrant-hostmanager](https://github.com/devopsgroup-io/vagrant-hostmanager)とかもあるが、[vagrant-hostsupdater](https://github.com/agiledivider/vagrant-hostsupdater)を使ってみる。

`Vagrantfile`に書いた接続情報をホストOS（e.g. mac）の`/etc/hosts` に設定してくれるプラグイン。
仮想マシンにアクセスするときに、ホスト名から接続できるようになる。。
加えて、仮想マシンを作成するたびに、本来なら`/etc/hosts`を自分で開いて、ドメインIPアドレスの設定をしなきゃいけないけど、その手間が省けるので便利。


#Vagrantfileに設定情報を書く
Vagrantfileは、`Ruby`で書かれている。

##Vagrantバージョンの指定
```ruby
Vagrant.require_version ">= 1.3.5" #1.3.5 or greater.
Vagrant.require_version ">= 1.3.5", "< 1.4.0" #range specified
```
###<解説>
- Vagrantfileの一番上に記述する。
- 互換性の問題防止のために、設定する。


##仮想マシンの設定項目(config)を指定
```ruby
## Version constraint
Vagrant.require_version ">= 1.3.5"

## Plugin constraint
unless Vagrant.has_plugin?("vagrant-hostsupdater")
  raise 'Missing plugin `vagrant-hostsupdater`! Install it by `vagrant plugin install vagrant-hostsupdater` command before vagrant up.'
end

Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"
  config.vm.box_version = "2004.01"
  # config.vm.box_url = "https://cloud.centos.org/centos/7/vagrant/x86_64/images/CentOS-7-x86_64-Vagrant-2004_01.VirtualBox.box"
  config.vm.hostname = "vagrant-test.localhost.com"
  config.vm.network :forwarded_port, guest: 5000, host: 8080, id: "http", protocol: "tcp"
  config.vm.network :private_network, ip: "192.168.10.10"
  config.vm.provider :virtualbox do |v|
      v.name = "centos7_vagrant_test"
      v.customize ["modifyvm", :id, "--memory", 2048]
      v.cpus = 1
      v.check_guest_additions = false
      v.functional_vboxsf     = false
      v.gui                   = false
  end
  config.vm.synced_folder ".", "/home", id: "home", type: "nfs", :nfs => true, :mount_options => ['nolock,vers=3,udp,actimeo=2']
  config.vm.provision "shell", inline: <<-SHELL
    echo Hello, World
  SHELL
  # config.vm.provision "shell", inline: <<-SHELL
  #   /home/init.sh
  # SHELL
  # $DOCKER_COMPOSE_VERSION="1.28.2"
  # config.vm.provision "shell", :path => "home/docker.sh", :args => [$DOCKER_COMPOSE_VERSION]
  # config.ssh.forward_agent = true
end


```
###<項目解説>
| 変数名 | 説明 | 上記との対応 |
|:--|:--|:--|
| config.vm.box | 仮想マシンで利用するBOX名 | centos/7 |
| config.vm.box_version | 仮想マシンで利用するBOXのバージョン | 2004.01 |
| config.vm.box_url | 仮想マシンで利用するBOXのURL<br>VagrantCloudのboxの省略形の場合、指定しなくていい。 | ※コメントアウトしてる|
| config.vm.hostname | 仮想マシンに設定するホスト名 | vagrant-test.localhost.com |
| config.vm.network | 仮想マシンに設定するネットワーク接続<br>forwarded_port、private_network、public_networkが指定可能。 | :forwarded_port, guest: 5000, host: 8080, id: "http", protocol: "tcp"<br>:private_network, ip: "192.168.10.10"|
| config.vm.provider | 仮想マシンを作成するソフトウェアの構成設定 | :virtualbox |
| config.vm.synced_folder | ホストとゲストとの間で共有するフォルダ |".", "/home", id: "home", type: "nfs", :nfs => true, :mount_options => ['nolock,vers=3,udp,actimeo=2']|
| config.vm.provision | 仮想マシン作成時のプロビジョニング方法 |"shell", inline: <<-SHELL echo Hello, World SHELL|

####<詳細説明>
- `Vagrant.configure("2") do |config|`は設定バージョンを表す。
    -  `"2"`は`Vagrant 1.1+ 〜 2.0.x`の設定に対応
- ゲストの5000番に、ホストの8080番ポートのアクセスを設定、設定の名称は`http`
- `functional_vboxsf`:共有フォルダの有効/無効設定
- `check_guest_additions`:trueなら`Guest Additions`（**VirtualBoxの操作性を向上させるためのモジュール**）があるかチェック
    - Guest Additionsの利用目的は下記
        - シームレスなマウス操作
        - 共有フォルダー
        - デスクップ解像度の変更
        - シームレスなウィンドウサイズの変更
        - ホストとの時刻の同期
        - クリップボードの共有
        - オートログオン
- `gui`：GUI付きでVirtualBoxを立ち上げるかどうか
- `synced_folder`：デフォルトは、`/vagrant`のディレクトリにマウントされる。
    - 第１引数：ホスト側の共有ディレクトリ
        - 絶対パス、相対パスのいずれも使用可能、相対パスのルートはプロジェクトのルート
    - 第２引数：ゲストマシン側の共有先ディレクトリ
        - 絶対パスで記載する必要あり
    - `type`：同期方法の指定
        - デフォルト:指定しない場合は最適なタイプを選んでくれる
        - `nfs、rsync、smb`が選択可能（[synced_folderのoptions](https://www.vagrantup.com/docs/synced-folders/basic_usage)）
            - `rsync`：ホストOSからゲスト仮想マシンに、1回限りかつ一方向の同期を実行
            - `smb`（サーバメッセージブロック）：通信プロトコル。ファイルやプリンタを共有するときに使用。主にWindowsのパソコンで使われてる
        - `mount_options`：マウント方法を指定。例えば、アクセス権とかも
            - 参考：[mount_options](https://man7.org/linux/man-pages/man8/mount.8.html)
            - 参考：[nfs options](https://man7.org/linux/man-pages/man5/nfs.5.html)
    - `nolock`：ロックを無効に。ファイルを読み取るだけの場合は、使用するとパフォーマンス向上するケースも。
    - `<<-`：を用いることでTABによるインデントを無視できる
    - `<<-SHELL`：GitHub上にてヒアドキュメントの識別子にsyntaxの指定をすると、**GitHub Syntax Highlight**が効く
    - `NFSv3`の特徴 
        - IP ネットワーク経由で実行する`User Datagram Protocol(UDP)`を使用してクライアントとサーバー間のステートレスなネットワーク接続を実現
        - 完全な非同期書き込みに対応
        - エラー処理機能強化
        - 64ビットのファイルサイズ対応 (2GBを超えるファイルを扱える)


#Vagrantfileの読み込まれ方
```shell
vagrant up
```
でVagrantは立ち上がるが、Vagrantfileの探し方は、
現在いるディレクトリパスから探しに行って、順番に、上階のフォルダにあるか探しに行く挙動
なので覚えておくとよき。

```
/Users/username/src/github.com/dir/local/Vagrantfile
/Users/username/src/github.com/dir/Vagrantfile
/Users/username/src/github.com/Vagrantfile
/Users/username/src/Vagrantfile
/Users/username/Vagrantfile
/Users/Vagrantfile
/Vagrantfile
```


#ローカルで仮想マシン立ち上げ
見事立ち上がりました。（ほっ）

```
MacBook-Pro:local username$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: Checking if box 'centos/7' version '2004.01' is up to date...
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: Clearing any previously set forwarded ports...
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
    default: Adapter 2: hostonly
==> default: Forwarding ports...
    default: 5000 (guest) => 8080 (host) (adapter 1)
    default: 22 (guest) => 2222 (host) (adapter 1)
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: Running 'pre-boot' VM customizations...
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
==> default: Machine booted and ready!
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: Setting hostname...
==> default: Configuring and enabling network interfaces...
==> default: Rsyncing folder: /Users/username/src/github.com/dir/local/ => /vagrant
==> default: Exporting NFS shared folders...
==> default: Preparing to edit /etc/exports. Administrator privileges will be required...
Password:
==> default: Mounting NFS shared folders...
==> default: Machine already provisioned. Run `vagrant provision` or use the `--provision`
==> default: flag to force provisioning. Provisioners marked to run always will still run.
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: [vagrant-hostsupdater]   found entry for: 192.168.10.10 vagrant-test.localhost.com
```

###vagrant 停止

```shell
vagrant halt
```

#まとめ

おわり。