Windows10 で手軽にVMを作る（Vagrant）

※ 2020/03/02 時点の情報として、加筆修正してあります。

2018 年くらいから（というか結構前から？）、オープンソースソフトウェア（OSS）やマイクロサービスといった単語が当たり前のように浸透してきたIT業界に身を置いていると、仕事やプライベートでは Windows を使用していても、アプリケーションは Linux 上で構築することが当たり前になってきました。

そこで今回は、 Windows 上でも簡単に VM （仮想環境）を作成して Linux を動かせるようにするために、 Vagrant の使い方を説明していきます。
なるべく難しい説明は省き、簡単に書きます。まずは動作させることができるようになることが目標です。
理解は二の次です。間違っていたらごめんなさい。

# Vagrant とは何か？

VM を気軽に構築するためのツール、とでも言いましょうか。
実際の VM は、 VirtualBox だったり VMWare Workstation Player 上で構築されることになると思います。
Vagrant は、これら VM をコマンドライン経由でサクッと作成するためのツールだと考えておいていいかと思います。
読み方は、ヴェイグラントです。

# そもそも VM とは？

仮想環境、と言っても、イメージつかない人もいますよね。
今このページを見ている端末（PCやらスマホやら）の OS は Windows だったり Android だったり iOS だったり、 OS X だったりするわけです。
それら OS の上で、別の OS を動かすための環境が仮想環境、という感じです。
今回でいえば、いつも通り PC の電源ボタンを押して Windows10 を起動して、ログインした後に、 Windows10 の上で Linux の OS が起動されているイメージです。
Linux って何？ って聞かれたら、 OS の一種です。と答えます。
Android も Linux の一種です。
ちょっと脱線しますが、 Linux のディストリビューションとして Redhat Enterprise Linux （いわゆる RHEL ）や CentOS があります。（ Android もディストリビューションですかね）
ディストリビューションとは、要するに誰でも Linux を使えるように、 Linux を操作するために必要なソフトウェアやら何やらを一緒にしたもの、という感じですかね。
テレビを操作するためにリモコンを使う、みたいな感じですかね。テレビだけじゃなく、リモコンもセットになって初めて誰でもテレビの機能を使えるようになる、みたいな。
・・・なんか違う気がする😅

かなり脱線しましたが、今回の例では Windows 上で、例えば CentOS を動かすイメージ、と言えますが、別に Windows 上で Windows を別途動かしてもいいですし、 OS X 上で Windows を動かしてもいいわけです。
要するに PC に直接インストールされた OS とは完全に切り離された別の OS を PC 上の OS のさらに上で動かせるようにするものが仮想環境です。
厳密には仮想環境にはホスト型、ハイパーバイザー型、コンテナ型という3種類があったりしますが、ここではそれらを意識する必要はありません。
あえて言えば、今回学ぶ Vagrant はホスト型です。

# 学ぶための準備

さて、学んでいきましょう。
今回、題名にもある通り、 Windows10 の上で構築することを前提にしています。
これは、 Vagrant の実行には裏で PowerShell という、 Windows 独自のスクリプトが利用されていて、この PowerShell のバージョンが古いと Vagrant が正しく動かないため、たとえば Windows7 で最新の Vagrant をインストールするとハマるからです。
何も考えずに使えるようになるため、 PC は Windows10 を用意しましょう。
MAC ユーザーは、おそらくこの記事を読まなくても自分で調べてできると思います。

あと、 Vagrant はあくまで VM を構築しやすくするためのツールなので、 VM 自体が稼働するためのアプリケーションが別途必要です。（上の方でちらっと説明しましたね）
今回は VirtualBox を利用します。
VirtualBox は Oracle のソフトウェアなので、[こちら](https://www.virtualbox.org/) からダウンロードしてください。
ダウンロードしたらそのままインストールしてください。
バージョンは 6.1 系だと思います。

次に、 Vagrant をインストールします。
[こちら](https://www.vagrantup.com/) からダウンロードしてインストールしてください。
バージョンは 2.2.7 だと思います。
※ Vagrant のインストールでは、再起動が必要です。

ここでなぜバージョンを記載したかというと、 VirtualBox のバージョンが上がってしまうと Vagrant で操作ができなくなるからです。
少し前、 VirtualBox6.1 が出た当初はまだ Vagrant2.2.6 だったため、 VirtualBox6.1 は操作出来ませんでした。
そんな時は、アーカイブから古いバージョンの VirtualBox をダウンロードしてインストールする必要があります。
古いバージョンは [こちら](https://www.virtualbox.org/wiki/Download_Old_Builds) からダウンロード可能かと思います。
リンクが切れたら、ごめんなさい。

# Vagrant の基本操作

先走りますが、操作説明をします。
VirtualBox と Vagrant を何も考えずにインストールしてもらったので、何が何だか分からないと思います。
そこで、まずはコマンドプロンプトを立ち上げてみましょう。
キーボードの ウインドウズキー + R を押すと、「ファイルを指定して実行」が開きますので、そこに「cmd」と入力してエンターキーを押します。
そうすると、コマンドプロンプトが立ち上がります。
ここに、コマンドを打っていきます。
以下のような種類があります。

### vagrant version

Vagrant のバージョンを見るコマンドだと思います。
実務上、使いません😛

### vagrant global-status

これは、Vagrant で管理している VM の一覧を見るためのコマンドです。
各 VM に割り当てられた ID を用いて vagrant コマンドで操作可能なので、このコマンドにより ID を調べる必要があります。

### vagrant init

VM の初期化をします。
実際には、 vagrant で扱うための VM の設定情報を記載する Vagrantfile というものが作成されるだけです。
Vagrantfile がカレントディレクトリ上に作成されるため、あらかじめ Vagrant 用にフォルダを作っておいた方が管理が楽になります。
コマンドの使い方は、以下のようにします。

```console
vagrant init bento/centos-8
```
上記は、 bento/centos-8 という VM イメージを用いて VM を作成する準備をしています。
VM イメージは、 [Vagrant Cloud](https://app.vagrantup.com/boxes/search) から検索できます。
あらかじめ用意された VM イメージを使って手軽に VM を作成できるのが、 Vagrant のいいところです。

### vagrant up

VM を起動します。
基本的には `vagrant up {ID}` で指定した VM を起動することが多いですが、 `vagrant init` したばかりの場合は ID がないため、 Vagrantfile があるフォルダ上で `vagrant up` します。
つまり、 `vagrant init` したら `vagrant up` はセットで行う、と考えていいです。

### vagrant halt

起動中の VM を停止します。要するにシャットダウンです。
この時も、 `vagrant halt {ID}` で指定した VM をシャットダウンします。
`vagrant halt` 単体の場合、実行したカレントディレクトリに Vagrantfile があれば、その対象 VM をシャットダウンします。

### vagrant destroy

いらなくなった VM を物理的に削除します。
VM は、削除しない限りハードディスクに残ったままです。
PC を買い替えてデータだけ移した場合、 Vagrant 管理の VM は VM としては残っていますが Vagrant で操作できなくなりますので、いらない VM は削除しておくことをお勧めします。
最悪、ハードディスク上のファイルを削除すればなんとかなります。
一応 Vagrant 管理下に戻すことも可能らしいです。
しかし、 Vagrant を使用するのであれば VM は使い捨て、くらいに思っておいた方がいいかもしれません。

---

コマンドは、基本的に上記5つ（一番上は不要）を主に使います。
以下のコマンドは、より実践的なものになります。

### vagrant package

VM 上に色々と構築したのでこの状態を保存しておきたい！ という時に、そのイメージを box ファイルというものに書き出すために使用するコマンドです。
`vagrant halt` でシャットダウンしたのち、 box ファイルにしたい VM の Vagrantfile があるフォルダ上で `vagrant package` を実行すると、 `package.box` というファイルが作成されます。
ここでも ID 指定にすればいいじゃないか、と思うかもしれませんが、どの VM の box ファイルを作成したのかが追いづらくなるので、 Vagrantfile とセットにしておいた方が最初は楽かなと思い、そのようにしています。

### vagrant box add

package.box を vagrant init の際に指定できる VM イメージとして登録するために使用するコマンドです。
`vagrant box add {package.box} --name {イメージ名}` という書式だったと思います。
毎回忘れます。😛

---

# VMを立ててみる

Vagrant の操作だけ分かっても、操作対象の VM を構築しないと始まりません。
Vagrant では、先ほどちらっと話しましたが [Vagrant Cloud](https://app.vagrantup.com/boxes/search) というところで VM のイメージが公開されています。
要するに、 VM として動作するように OS にあらかじめ色々と設定を加えた状態のものを配布している、ということです。
今回は CentOS7.3 でも入れてみましょうかね。

## bento/centos-7.3 を使う

Vagrant の中では有名な bento というプロジェクトのイメージを使用します。
[こちら](https://app.vagrantup.com/bento/boxes/centos-7.3) ですね。
先ほどのコマンドプロンプトは、まだ立ち上がったままでしょうか。
まずは、VMを構築するためにフォルダを移動しましょう。
例えば、Dドライブ直下の `Virtual Machines` フォルダに移動するなら以下のように入力し、実行します。
（ここからは、自身の環境に合わせ、フォルダ名は適宜読み替えて進めてください）
`cd /d "d:\Virtual Machines"`
VMを入手するため、以下のコマンドを入力します。
`vagrant init bento/centos-7.3`
そうすると、 `d:\Virtual Machines` フォルダに、 `Vagrantfile` ファイルが出来上がります！
サクラエディタなどのテキストエディタで、 Vagrantfile を開きましょう。
そうすると、以下のような記述が見つかるかと思います。

```bash
# config.vm.network "private_network", ip: "192.168.33.10"
```

この先頭のハッシュタグはコメントアウトなので、外します。
つまり、 `#` を削除します。
IP アドレスは、この VM に Windows からアクセスするためのものなので、末尾の `10` の部分だけを変更します。
IP アドレスの理解がなく不安な場合は、変えなくても問題ありません。
（ほかに同じ IP アドレスで VM を構築していることがなければ、変更しなくても影響は無いはずです）

まだコマンドプロンプトは立ち上げていますか？
また、今いるフォルダは `d:\Virtual Machines` のままでしょうか？
そうなら、そのまま `vagrant up` と入力し、エンターキーを押してみてください。
そうすると、あら不思議、何やら動いて、 VM が起動します。
（時間がかかるので、しばらく待ちます）

ちゃんと起動できたかどうか、 `vagrant global-status` と入力しエンターキーを押して、 ID が発行されているか確認します。
発行されていますよね。

# ssh で入ってみる

teraTerm などの ssh クライアントを使用して先ほどの `192.168.33.10` もしくは変更していればその IP アドレスに、 ssh でログインしてみます。
ssh クライアントのお勧めは、 [RLogin](http://nanno.dip.jp/softlib/man/rlogin/) です。とてもお世話になっています。
手元に ssh クライアントがなく、また ssh もよく分からない、という場合には、 Vagrant がコマンドを用意しているので焦る必要はありません。
`vagrant global-status` で ID を調べたら、 `vagrant ssh {ID}` で、コマンドプロンプト上で VM にログインできます。
ssh クライアントと違い、ちょっと見づらいかもしれません。
コマンドプロンプトは文字コードが Shift_JIS ですが、たいていの ssh クライアントは UTF-8 です。
また、今回使用する CentOS7.3 も、文字コードは UTF-8 がデフォルトです。
そのため、コマンドプロンプト上でマルチバイト文字を表示させると文字化けするかもしれません。

脱線から戻り、とりあえずログインしたら、　`[vagrant@localhost ~]$` みたいな表示になりますよね。
これがログインできている証拠です。
試しに CentOS のコマンドを入力してみましょう。
`cat /etc/redhat-release` と入力してエンターキーを押してみてください。
そうすると `CentOS Linux release 7.3.1611 (Core)` みたいに表示されませんか？
表示されたのなら、 ssh での接続と CentOS に対するコマンド実行は成功しています。

# VM を落とす

先ほど ssh で入ったので、今度は `exit` と入力して VM から抜けましょう。
そのあと、先の説明にあった `vagrant halt {ID}` をやりましょう。
なお、今更ですが波括弧は不要です。変数ですよ、の合図なだけですね。
`vagrant halt` のコマンドでVMが停止したら、 `vagrant global-status` で状況を確認するのも忘れずに。
`poweroff` と表示されているはずです。

# VM を削除する

先ほど説明した通り、 `vagrant destroy {ID}` で削除します。
削除した結果、 `vagrant global-status` を打っても、何も出ませんよね。
削除成功です。

# なぜ Vagrant がいいか

ここまでやってきて、詳しい人なら「別に VirtualBox で直接操作すればよくね？」という人もいるかもしれません。
しかし、試しに `vagrant box list` と入力してみましょう。
`vagrant init` で使った `bento/centos-7.3` が一覧に出てきていると思います。
`vagrant init` により、ローカルにキャッシュされているということです。
また、作成された `Vagrantfile` があれば、いつでも同じVMイメージを使って VM を構築できます。
（厳密にいえば、 `bento/centos-7.3` がバージョンアップすると VM も勝手にバージョンアップしてしまうかも）
そのため、さっき `vagrant destroy` で削除しましたが、また Vagrantfile のあるフォルダで `vagrant up` を実行すれば、その Vagrantfile の内容に従って VM が構築されます。

一昔前は、例えば CentOS7 の ISO ファイルを CentOS のサイトからダウンロードしてきて、 VirtualBox を起動し、新規 VM の作成から ISO ファイルを指定して起動して OS のインストール手順を実行して時間をかけて構築していたものが、すぐに終わるようになりました。
つまり、簡単に VM が作成できるようになったので、さくっと VM を作成し、そこにアプリケーションを構築したりちょっと動かしてみたいだけのスクリプトを配置してみたり、最悪 OS が死んでも `vagrant destroy` で削除して `vagrant up` でまた作り直せばいいわけです。
すんごい楽ですね。
より上級者になれば、ある程度構築した段階で package.box を作成しておいて、何か問題があって VM を削除しなくてはいけなくなったとしても package.box の状態は復元可能になります。
これは、慣れたら手放せないですね。

# 最後に

なるべく難しいことはせずに簡単に書きました。
簡単すぎて意味ないかもしれませんが、全く vagrant を使ったことないのに（仕事の都合上とかで）いきなり使う羽目になった人の為に書きました。
難しい話は、ここから勉強してみてください。
私も、今回の説明以外では Vagrantfile の

```bash
# config.vm.synced_folder "../data", "/vagrant_data"
```
の部分を書き換えて Windows 上のファイルをVMとマウントして使うことくらいしかしてないかも・・・
余談ながら上記の設定について説明すると、この設定をすることによって Windows 上のフォルダと VM 上のディレクトリ間で同期をとることができます。
つまり、 Windows 上でファイルを編集したら、そのまま VM 上で扱えるようになっています。
設定例は、以下のように書きます。

```console:Vagrantfile
config.vm.synced_folder "D:/program_src/test", "/vagrant_data"
```

設定ファイルではバックスラッシュは使えず、スラッシュに置き換える必要があるので注意してください。
この設定により、 Windows 上の D:\program_src\test 配下のファイルを編集したり、ファイルを配置したりするとそのまま VM 上の /vagrant_data 配下に反映されます。
なお、実は Vagrantfile があるフォルダ自体が、 /vagrant と同期しています。
なので、上記設定を入れなくても Vagrantfile のあるフォルダにファイルを配置するだけでも VM 上にファイルを送り込むことができたりします。

あとは、慣れてきたら、自分で box を作成して vagrant init してみるのもいいと思います。

それでは！