前回、仮想マシンのCentOS7でwebサーバーを立ち上げ、ブラウザで「Hello,World!」させてみました。
しかしこのままだと、仮想マシンで開発を行う時はファイルを全てssh接続した状態でviやvimエディタで編集しなくてはなりません。
これだとあまりに不便すぎます。
なので、今回はホストOS側(mac)で vs code や sublime text などのエディタを使ってファイルを編集し、それが自動で仮想マシン側へ反映されるようにしていきたいと思います。
仕組みは簡単で、ホスト側と仮想マシンとで共有して使えるフォルダ、「共有フォルダ」をドキュメントルートに設定するだけになります。
共有フォルダの場所を指定する
仮想マシン上のどのディレクトリと、mac側のどのディレクトリを共有するのかを設定します。
centos7 ディレクトリに移動し、Vagrantfileを編集しましょう。(仮想マシンと接続している人はログアウトしてください。)
Vagrantfileを開く
$ cd ~/centos7
$ vi Vagrantfile
「Share an additional folder to the guest VM.」に関する記述を探します。
以下のような記述です
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
# config.vm.synced_folder "../data", "/vagrant_data"
config.vm.synced_folderの行のコメントを外し、以下のようにします
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
config.vm.synced_folder "./data", "/vagrant/data"
こうすることで、mac上の「~/centos7/data」と、仮想マシン上の「/vagrant/data」が共有フォルダとして指定されます。
「config.vm.synced_folder "ホストOS上のディレクトリ", "仮想マシン上のディレクトリ"」で任意のディレクトリを指定することができます。自分にあった設定をしましょう。
設定を書き換えたので、vagrantを再起動しておきます。
この時、共有フォルダに指定したホスト側のディレクトリ(「~/centos7/data」ディレクトリ)は先に作成しておきましょう。そうしないと、以下のようにエラーが出て再起動されません。
ホスト側のディレクトリが準備されていない場合のエラーメッセージ
There are errors in the configuration of this machine. Please fix
the following errors and try again:
vm:
* The host path of the shared folder is missing: ./data
ディレクトリの準備ができたら再起動
$ vagrant reload
再起動中にエラーがでる場合はGuest Additionをインストールする
おい!再起動中にエラーメッセージが表示されたぞ!という方もいらっしゃるかと思います。
再起動中のエラーメッセージ
Vagrant was unable to mount VirtualBox shared folders. This is usually
because the filesystem "vboxsf" is not available. This filesystem is
made available via the VirtualBox Guest Additions and kernel module.
Please verify that these guest additions are properly installed in the
guest. This is not a bug in Vagrant and is usually caused by a faulty
Vagrant box. For context, the command attempted was:
mount -t vboxsf -o uid=1000,gid=1000 vagrant_data /vagrant/data
The error output from the command was:
mount: unknown filesystem type 'vboxsf'
このメッセージは、共有フォルダ機能が VirtualBox側 で有効になっていないのが原因です。
VirtualBoxで共有フォルダを有効化するには、「Guest Addition」という機能を別途インストールする必要があります。
しかし安心してください。Vagrantではこれを簡単にインストールしてくれるプラグインがあります。(ここで下手にGuest Additionのインストール方法を調べるとものすごく無駄な作業をしてしまうので、注意してください。)
vagrant-vbguestプラグインをインストール
$ vagrant plugin install vagrant-vbguest
プラグインがインストールできたら、以下のコマンドを実行するだけです。
Guest Additionのインストール
$ vagrant vbguest
無事にGuest Additionがインストールできたら、Vagrantをもう一度再起動してみましょう。
Vagrantの再起動にリベンジ
$ vagrant reload
起動中に、以下のようなメッセージが含まれていれば無事に共有フォルダは有効になっています!
成功メッセージ
[default] GuestAdditions 5.2.12 running --- OK.
共有フォルダの動作確認
共有フォルダがちゃんと機能しているか確認してみましょう。
仮想マシンヘ接続
$ vagrant ssh
CentOS側の共有フォルダ(「/vagrant/data」)にテスト用ファイルを作成
[vagrant@localhost ~]$ touch /vagrant/data/test
Mac側の共有フォルダ(「~/centos7/data」)をFinderで確認してみましょう!
無事に共有されていることがわかります!
逆に、mac上から適当にファイルを追加してみても、仮想マシン上で確認できると思います。
ドキュメントルートを共有フォルダに設定する
今回の最終目標です。ここまでで有効化してきた共有フォルダを、ドキュメントルートに設定していきましょう。
シンボリックリンクを作成する
方法は簡単で、ドキュメントルートである「/var/www/html」を、共有フォルダへのシンボリックリンクにするだけ。
まずは、今あるhtmlディレクトリを消去しましょう。
rmコマンドで削除
[vagrant@localhost ~]$ sudo rm -rf /var/www/html
前回の記事から続きで読んで下さっている方の場合、「Hello, World!」と表示させるだけの index.html ファイルがあると思いますが、不要なので気にせず消去。
続いて、シンボリックリンクを作成します。
/vagrant/data へのシンボリックとして /var/www/html を作成
[vagrant@localhost ~]$ sudo ln -fs /vagrant/data /var/www/html
シンボリックリンクができたか確認してみましょう。
「/var/www」ディレクトリへ移動
[vagrant@localhost ~]$ cd /var/www
htmlディレクトリの確認
[vagrant@localhost www]$ ls -l
drwxr-xr-x. 2 root root 6 Apr 20 18:11 cgi-bin
lrwxrwxrwx. 1 root root 13 May 26 10:24 html -> /vagrant/data
「html -> /vagrant/data」のようになっていればOK
確認できたら、一応httpdを再起動しておきましょう。
webサーバー(httpd)の再起動
[vagrant@localhost www]$ sudo systemctl restart httpd
新しいドキュメントルートにindex.htmlを作成する
さて、シンボリックリンクが作成できたら、新たなドキュメントルート「/vagrant/data」に index.html を作成し、ブラウザで確認していきましょう。
/vagrant/dataにindex.htmlを作成し、編集
[vagrant@localhost www]$ sudo vi /vagrant/data/index.html
index.htmlの中身(適当でいいです。)
<h1>Hello, World!</h1>
:wqで保存・viエディタを終了します。
「192.168.33.10」アクセスしてみると...
あれ?index.htmlの内容が表示されず、Testing画面が出てきてしまっています。
Testing画面が出ているということは、webサーバーに問題はないようですが。
また、「192.168.33.10/index.html」と明示的に index.html ファイルへアクセスしてみると、
「Forbidden」、つまり403エラーになっています。
index.html ファイルが見つからないわけではなく(その場合は404エラーとなる)、パーミッション的にアクセスできない状態だというですね。
このことから、ドキュメントルートの設定自体は問題なく共有フォルダの「/vagrant/data」になっていることが分かります。
結論から言うと、このエラーの原因は「SELinux」という、CentOS7のセキュリティシステムです。
403だ!パーミッションのせいだ!とパーミッションの設定にばかり目がいくととんでもなくハマりますので注意しましょう。chmodコマンドなどでは解決できません。
何が問題なのか
今回はただのパーミッションの問題ではなく、「SELinux コンテキスト」の不一致による問題です。
SELinuxコンテキストとは、SELinuxによってファイルにラベル付けされる情報のことです。
「ユーザー :ロール:タイプ :レベル 」という4種類の情報を持ちます。
ls -Z
コマンドでSELinux コンテキストを確認できるので、確認してみましょう。
共有フォルダ「/vagrant/data」のSELinux コンテキストを確認
[vagrant@localhost ~]$ ls -Z /vagrant
-rw-r--r--. vagrant vagrant unconfined_u:object_r:default_t:s0 Vagrantfile
drwxrwxr-x. vagrant vagrant system_u:object_r:vmblock_t:s0 data
data ディレクトリの方に注目してください。「system_u:object_r:vmblock_t:s0」が data ディレクトリのSELinux コンテキストになります。
SELinux有効時、httpd は SELinux コンテキストのタイプ情報が「httpd_sys_content_t」となっているディレクトリやファイルにしかアクセスすることができません。
しかし、 data ディレクトリのタイプ情報を見てみると、「vmblock_t」となっていますね。
これが原因で、403エラーとなってしまっていたのです。
SELinuxを無効にする
一番簡単な解決方法は、SELinuxの機能を無効にしてしまうことです。本番サーバーではなくただのローカル仮想マシンなので、無効にしておいて特に問題ないかと思います。
SELinuxの設定ファイルを編集
[vagrant@localhost ~]$ sudo vi /etc/selinux/config
中身(冒頭部分)
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=enforcing
上記の部分は、システム(仮想マシン)起動時のSELinuxの初期状態を設定しています。
「SELINUX=enforcing」というのは有効とする記述なので、この部分を「SELINUX=disabled」としておきましょう。
すると、次回システム起動時からSELinuxは起動しなくなります。
:wqで保存終了ができたら、一度 vagrant を再起動しましょう。
ログアウトして再起動
[vagrant@localhost ~]$ exit
$ vagrant reload
再起動完了後、もう一度「 192.168.33.10 」にアクセスしてみましょう。
無事、index.htmlの内容が表示されるはずです!
SELinuxを有効にしたまま解決する方法
これは完全に自己満足の領域です。ローカル環境ではSELinuxを無効にする方法で構いません。(ファイアウォールも切ってるくらいですから)
詳しく説明すると少し長くなってしまうのと、今回の主旨からは外れた内容なので、詳細は以下の記事にまとめています。
ざっくりとだけ内容を説明しておきますと、
SELinux コンテキストの「vmblock_t」タイプにはhttpdはアクセスできないことがエラーの原因だが、仮想マシン共有フォルダの「vmblock_t」というタイプは変更することができないので、「httpdくんは「httpd_sys_content_t」の他に「vmblock_t」の場合でもアクセスしていいよ〜。」という特別ルールを追加してあげる。
という感じになっています。
興味がある方、SELinuxについて深く知っておきたい方は是非参考にしてみてください。
おわりに
お疲れ様です。
無事にドキュメントルートを共有フォルダのシンボリックリンクに設定することはできたでしょうか?
今回はドットインストールを参考にして環境構築を始めたのでこのような形をとりましたが、シンボリックリンクを作らなくても、/var/www/htmlを直接共有フォルダに設定してもいいかもしれませんね...。