Homestead で、Laravel 開発環境を構築する手順


感想：サクッと始められるイメージだったけど、エラーが出て少しつらかった。

まずは Laravel の概要を知る
-------------------------------------------------------------

整理しきれていないけど、色んなサイトに載っていたものを羅列してみる

* 今旬の世界で人気のオープンソースのMVCフレームワーク
* 半年ごとに新しいバージョンがリリース
* TLS（Long Term Support）のバグ対応は２年、セキュリティ対応は３年
* Vue.js との連携がスムース
* 管理パネル [Laravel Horizon](https://laravel.com/docs/5.6/horizon) / [Laravel Nova](https://nova.laravel.com/) (有料)
* MITライセンス
* 土台は Symfony フレームワーク
* 学習コストが低い
* HTMLテンプレートエンジンは「Blade」
* キャッチコピーは "The PHP Framework For Web Artisans" (ウェブ職人のためのPHPフレームワーク)
* Web開発に便利なルーティング、MVC、ORマッパー、ジェネレータ等の機能が含まれており、Laravelの流儀にしたがって作れば、自然とわかりやすい構造のWebアプリケーションが作れる
* 自由なディレクトリ構成（名前空間の構成）
* バリデーション処理をコントローラーに記述
* ファイルアップロード処理が簡単
* よく使う機能をコマンド一発で実装できる
* 処理速度は CakePHP や Codeigniter に劣る
* ライブラリが豊富
* コードが読みやすく、書きやすい
* 学習コストの低さ
* 強力なルーティングフィルター
* 柔軟なオートローダー
* 簡単なページネーション
* ビューをサポートするコンポーサー

参考：[Laravel超入門 開発環境の構築 - Qiita](https://qiita.com/7968/items/97dd634608f37892b18a)
参考：[Laravelのリリース日と修正期間のまとめ - Qiita](https://qiita.com/ykhirao/items/576a9eea735f91350072)
参考：[CakePHP 3 よりも Laravel 5 を推したい理由 | 綺麗に死ぬITエンジニア](https://s8a.jp/cakephp-3-vs-laravel-5#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89%E5%87%A6%E7%90%86%E3%81%AE%E7%B0%A1%E5%8D%98%E3%81%95)


Laravel Homestead で、開発環境を構築
-------------------------------------------------------------

[Laravel Homestead](https://laravel.com/docs/master/homestead) (Laravel 公式の Vagrant + Virtualbox 環境) を使う。
Mac OS 直下の環境を複雑にせず、使い捨てできる安心感が大きなメリット。

軽い [Valet（ベレット）](https://readouble.com/laravel/5.6/ja/valet.html)、Docker で構築する [Laradock](https://laradock.io/) という選択肢もあり。


### Laravel Homestead （ホームステード）とは

* Laravel 公式の Vagrantbox。
* Laravel 開発に最適化した環境が設定済みの Vagrantfile
* 1コマンドでLaravel開発に必要なアプリケーションが入った仮想マシンを構築してくれる
* WordPress 開発に置ける [VCCW](http://vccw.cc/) のようなもの
* Homestead は、英語で家屋敷、農家、自作農場という意味

### インストールされるアプリケーション

仮想マシンを立ち上げると色々インストールされるが、Laravel を動かすのに必要なものは、OS、Webサーバー、PHP、データベースの4つ。Node や gulp、wp-cli なども入っており、フロントエンド開発もすぐに開始できる。セットアップ後の仮想マシンの容量は6GB弱になるので事前にストレージの空き容量を確認しておくこと
(※ この記事を書いた時点での Homestead の最新バージョンは v7.15.1)

* Ubuntu 18.04 (Linux OS)
* PHP 7.2 (7.1, 7.0, 5.6)
* Composer (PHPモジュールのパッケージ管理)
* Nginx（Webサーバー）
* MySQL, PostgreSQL, Sqlite3（データベース）
* Redis（キーバリューストア、NoSQL ≒ データベース ※1）
* Memcached（汎用の分散型メモリキャッシュサーバ ※2）
* Node (With Yarn, Bower, Grunt, and Gulp) JS、開発でも使う
* Go (Go言語)
* Git (バージョン管理)
* wp-cli (WordPress コマンド操作)
* Beanstalkd (キュードライバ(処理の永続化、タスク監視))
* Mailhog (管理画面付きの開発用メールSMTPサーバ)
* ngrok (ローカルWebサーバを外部公開)
* Zend Z-Ray (プロファイラ＆デバッガ)
* Minio (Amazon S3のクローンプロダクト、S3互換)
* オプションでインストール可能
  - Apache (Webサーバー)
  - MariaDB (MySQL互換のデータベース)
  - Neo4j (グラフデータベース)
  - MongoDB (NoSQL データベース)
  - Elasticsearch (全文検索エンジン。RESTfulインターフェース、SQL使用不可)

※1) キャッシュ、カウンター、リアルタイムな集計や出力、などRDBMSに負荷がかかるような処理を軽く早くこなす
※2) データベースへの問合せ結果のキャッシュとして使うことで、データベースへのアクセス回数を減らし、動的なウェブアプリケーションのレスポンスやスケーラビリティを引き上げることができる


## インストールの手順

[Laravel Homestead 公式マニュアル](https://laravel.com/docs/5.6/homestead) の通り進める。  合わせて [Developer Blog: Laravel5.5の開発準備（Homestead）](https://k10i-tech.blogspot.com/2017/10/laravelhomestead.html)も参考にした。途中、記載の手順通りだとうまくいかない箇所もある。

以下の順で進める。
途中、ローカル(Mac)側の設定が必要な場面もある。

1. box の追加
2. Homestead の導入
3. 設定ファイル Homestead.yaml の編集
4. 仮想マシンを立ち上げる

### 0. 事前の準備

VirtualBox, Vagrant を最新版にしておく

### 1. Box の追加

`vagrant box add laravel/homestead`
途中、どの環境にインストールするか聞かれるので virtualbox を選ぶ


### 2. Homestead の導入

`git clone https://github.com/laravel/homestead.git ~/Homestead`

最新リリースがダウンロードされる。
この時点でのファイル構成は以下の通り

```
 ~/Homestead
    .editorconfig
    .git/
    .gitattributes
    .github/
    .gitignore
    .travis.yml
    bin/
        homestead
    CHANGELOG.md
    composer.json
    composer.lock
    init.bat
    init.sh
    LICENSE.txt
    phpunit.xml.dist
    readme.md
    resources/
        after.sh
        aliases
        Homestead.json
        Homestead.yaml
        localized/
    scripts/
    	シェルスクリプトファイル群
    src/
        MakeCommand.php
        Settings/
        Traits/
    tests/
    Vagrantfile
```

ダウンロードが完了したら、ホームディレクトリ/Homestead に移動
`cd ~/Homestead`


（安定版を使いたいなら）Homestead のブランチを切り替える ([リリース履歴](https://github.com/laravel/homestead/releases))。デフォルトは master。今回は切替えせずに進める
`git checkout v7.14.2`


初期化。
`bash init.sh`
aliases、after.sh、Homestead.yaml が生成される

Homestead.yaml は設定ファイル。
このファイルに立ち上げる仮想マシンの設定を書いていく。

### 3. 設定ファイル Homestead.yaml の編集

項目 folders には、ローカルマシン(Mac) と仮想マシンで共有したいフォルダを指定する。リスト形式で複数のフォルダも指定もできる。

仮想マシン側の共有フォルダは、map: で、デフォルトで /home/vagrant/code/

ローカルマシン側の共有フォルダは自由に指定すれば良いが、この段階できちんと決めておいた方が良い。デフォルトでは、ユーザーディレクトリ直下の code/ となっている。

デフォルト設定は以下。

```Homestead.yaml
folders:
    - map: ~/code
      to: /home/vagrant/code
```

同時に、ローカルマシン側のユーザーディレクトリ直下に code フォルダを作成しておく
`mkdir ~/code` (権限は 755 `chmod 755 ~/code`)

共有フォルダの同期は、デフォルトの VirtualBox の rsync では遅い。代わりに NFS を使うことで早くなる。その設定を追記する。（rsync を使う場合は、この文書下部のメモ「（NFS でなく rsync を使う場合のみ）共有フォルダの同期設定」を参照）。

先程の設定に `type: "nfs"` を付け加える
※ 後で vagrant-bindfs プラグインを入れる必要がある (後述)

```Homestead.yaml
folders:
    - map: ~/code
      to: /home/vagrant/code
      type: "nfs"
```

参考：[Vagrantのshare folderが遅い時はNFSを使うといいです - Qiita](https://qiita.com/itopan88/items/06d7c7a08f2d681b042a)



続けて、NFS に必要な設定をする。
自動で設定してくれていたが一応メモしておく

`sudo nfsd status` で nfsd が走っているか確認。
走ってなければ `sudo nfsd start` (もしくは enable）で起動（停止は `sudo nfsd stop`）。

/etc/exports が必要。すでに存在するか確認
あれば中を見てみる `cat /etc/exports`

```
# VAGRANT-BEGIN: 501 5f16acc2-cb08-49a8-ae65-cf5deeb73797
"/Users/ユーザー名/code" 192.168.10.10 -alldirs -mapall=501:20
# VAGRANT-END: 501 5f16acc2-cb08-49a8-ae65-cf5deeb73797
```

書式が正しいかチェック
`nfsd checkexports` (問題ないなら何も出ない)
なければ作成 `sudo touch /etc/exports`

`sudo nfsd update` で /etc/exports を再読込みする


【メモ】
必要なら `php: "5.6"` 追記で PHP のバージョン指定ができる (※ Nginx のみ、Apache は非対応)


【メモ】
複数プロジェクトを管理する場合は、パフォーマンス的な問題を避けるため、このディレクトリ下にプロジェクトごとにディレクトリ（例：/home/vagrant/code/laravelapp, /home/vagrant/code/project2）を作り、後述の sites で複数プロジェクトを指定すればよい。

分けることで、プロジェクトごとに folders の設定（オプション、NFS）をプロジェクトごとに設定することもできる

```Homestead.yaml
folders:
    - map: ~/code/laravelapp
      to: /home/vagrant/code/laravelapp

    - map: ~/code/project2
      to: /home/vagrant/code/project2
```



### 名前解決 (ドメイン名でアクセス → 指定フォルダ) の設定

Homestead と ローカル環境の Hosts ファイルの編集が必要

#### Homestead.yaml の設定

必要な Laravel プロジェクト数分を、リストで付け加えることができる
TLD（トップレベルドメイン、末尾の .com みたいな）は、開発用・テスト用なら[予約済みドメイン](https://blog.jxck.io/entries/2017-09-27/example-local-test-domains.html) (.example, .localhost, .test) を使う。
※Homestead.yaml の変更を反映する時は、再プロビジョニング(`vagrant reload --provision`)が必要

**※ 【重要】↓ public までのパスが必要。public がないと 403 forbidden エラーになる
　公式マニュアル他のサンプルでプロジェクトディレクトリまでのパスとなっているので注意**

```Homestead.yaml
sites:
    - map: laravelapp.test
      to: /home/vagrant/code/laravelapp/public

sites:
    - map: project2.test
      to: /home/vagrant/code/project2/public
```

#### Hosts ファイルの設定（ローカルマシン側）

名前解決（ドメイン名でアクセス → 指定 IP アドレスに飛ぶ）をさせるために必要
場所は /etc/hosts (/private/etc/hosts のエイリアス)

vagrant up 時に自動で設定してくれる。
`cat  /etc/hosts` で以下2つの設定が追記されていることを確認。
(2つめは Homestead.yaml の sites:  map で設定したドメイン)

```
192.168.10.10  homestead  # VAGRANT: 21faf90fac0d2f6e7cb0741d89dfd8fe (homestead-7) / 91999270-5349-41d6-925e-73dbe28d4484
192.168.10.10  laravelapp.test  # VAGRANT: 21faf90fac0d2f6e7cb0741d89dfd8fe (homestead-7) / 91999270-5349-41d6-925e-73dbe28d4484
```

~~不要：Homestead.yaml の sites:  map で設定したドメインをセットする。
例えば `192.168.10.10  laravelapp.test ` だと、ブラウザから laravelapp.test にアクセスすると、仮想サーバー (Homestead.yaml で設定した 192.168.10.10) に繋がる。~~




#### 認証鍵の設定（ローカルマシン側）

ローカルマシンから仮想マシンにログインパスワードなしで SSH 接続（鍵認証）できるようにする。

##### 公開鍵、秘密鍵を生成し、Homestead.yaml に指定

ローカル側(Mac、場所はどこでも) で鍵生成
`ssh-keygen`

"Enter file in which to save the key" と聞いてくるので、ファイル名を指定する。
デフォルトは /Users/ユーザー名/.ssh/id_rsa だが、複数の鍵を管理するなら各々のファイルを作り、config で管理するのが良い。

今回は /Users/ユーザー名/.ssh/homestead_rsa (ユーザーディレクトリは ~/ と記述可) とした。パスフレーズを聞いてくるので、必要なら設定する (後で `ssh-keygen -p` で変更可)。

指定した場所に homestead_rsa (秘密鍵) と homestead_rsa.pub (公開鍵) ができているのを確認。 Homestead.yaml の authorize: に公開鍵、keys: に秘密鍵をセットする。

```Homestead.yaml
authorize: ~/.ssh/homestead_rsa.pub

keys:
    - ~/.ssh/homestead_rsa
```

##### SSH config ファイルに追記

/Users/ユーザー名/.ssh/config に以下を追記。無ければファイルを新規作成する。

```.ssh/config
Host laravelapp (Laravel Homestead)
    HostName laravelapp.test
    Port 2222
    User ★★自分のユーザー名（Mac のユーザー名と同じ）
    IdentityFile ~/.ssh/homestead_rsa
    IdentitiesOnly yes
    # PreferredAuthentications password
```

* 参考：[Laravel ports 一覧](https://laravel.com/docs/master/homestead#ports)
* 参考：[SSHなるものをよくわからずに使っている人のための手引書 - Qiita](https://qiita.com/kenju/items/b09199c4b3e7203a2867)


#### ここで一段落してチェック

ここまでの Homestead.yaml を確認
ちなみに冒頭の `---` は、ファイルの初めという意味の記述なのでミスではない

```Homestead.yaml
---
ip: "192.168.10.10"
memory: 2048
cpus: 1
provider: virtualbox

authorize: ~/.ssh/homestead_rsa.pub

keys:
    - ~/.ssh/homestead_rsa

folders:
    - map: ~/code
      to: /home/vagrant/code
      type: "nfs"

sites:
    - map: laravelapp.test
      to: /home/vagrant/code/laravelapp/public

databases:
    - homestead
```

念のため、ローカルマシン側に前ステップで作成済の共有フォルダが存在することを確認。
（今回の例では、ユーザーディレクトリ/code）


### 4. 仮想マシンを立ち上げる

いざローンチ。

`vagrant up`（再起動は `vagrant reload`）

構築に数分かかる。途中、Macのパスフレーズが必要


### 確認

この時点ですでに仮想マシンにログインしているか確認。
ログインできておらず、"Bad owner or permissions" と出てる場合は
`chmod 600 ~/.ssh/config`

`php -v`、`laravel -v`、`nginx -v`、`composer -v`、`mysql -v` などで、インストールされているアプリケーションのバージョンやコマンドをざっと確認。

ブラウザから Homestead.yaml の sites で設定したURL（今回は http://laravelapp.test/）を入力しアクセス。今の時点では "No input file specified." と表示されたらOK。


### （ファイル共有を NFS にした場合のみ必要）vagrant-bindfs プラグインのインストール

[vagrant-bindfs](https://github.com/gael-ian/vagrant-bindfs) プラグインは、Homestead box 内のファイルやフォルダへのアクセス権限(user,group)を正しく維持してくれる。 このプラグインを入れないと、仮想マシン側のファイルの権限の変更ができない。なので入れる。

`vagrant plugin install vagrant-bindfs`

プラグインをインストール後、VagrantFileの末尾（最後の end の前の行）に以下を追記。

```
config.bindfs.bind_folder "~/code", "/home/vagrant/code"
```

リロード＆プロビジョニング
`vagrant reload --provision`

これで、権限も同期できるようになった。
権限を変えてみて、同期しているファイルの権限が同じように変わっているか確認する。

参考：[ゲストOS内ファイルの所有者が変わってしまう](https://yyuuiikk.org/entry/380)


### Laravelのプロジェクトを作成し、Webサーバーを起動

ここまで来たらもう少し。
Laravel を Symfony経由でダウンロード＆インストール。
自分の環境では、約2分かかった。

仮想マシンにログイン
`vagrant ssh`(ログイン時 /home/vagrant/ にいる)

グローバルの composer のアップデートが[必要？](https://qiita.com/y_UM4/items/2148621adeb1336d28df)  一応アップデートしとく。
`composer global update`


仮想マシンの /home/vagrant/code に移動しLaravel をインストール、
`cd code`
`laravel new laravelapp`
(もしくは `composer create-project --prefer-dist laravel/laravel laravelapp`)

Laravel のプロジェクトフォルダ (/home/vagrant/code/laravelapp/中に色々)が生成されていることを確認

ローカルマシン(Mac)の共有フォルダにも反映されていることを確認（ホームディレクトリ/code/laravelapp）。


アプリケーションフォルダに移動しサーバーを起動
`cd laravelapp`
`php artisan serve`

ブラウザで指定した URL にアクセスし、「Laravel」のタイトルが表示されていたら OK。

ちなみに、nginx の設定ファイルの場所は、
/etc/nginx/nginx.conf

中身に目を通し、ざっと把握しておくと良い。

"# Virtual Host Configs" の項で、
今回立ち上げた Laravel プロジェクトの設定をインクルードしているのが確認できるので、これも中を見ておく
`cat /etc/nginx/sites-enabled/laravelapp.test`

server > root に Homestead.yaml で設定した site > to がセットされているのが確認できる


nginx のエラーログの場所は、

* /var/log/nginx/laravelapp.test-error.log error (Laravel)
* /var/log/nginx/access.log (アクセスログ)
* /var/log/nginx/error.log (エラーログ)


サーバー停止は
`Control + c`


うまくいったら、git を導入しこの状態をコミットしとく

```
git init
git add .
git commit -m "Initial Commit"
```

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


## 上手くいかない時

### nginxのエラーログを確認

* /var/log/nginx/laravelapp.test-error.log ※laravelapp.test は指定したURL
  （メモ：同階層に error.log、access.log もある）

### エラー 403 Forbidden の対処法

ハマった。sites を以下のように変える

```
sites:
- map: homestead.app
  to: /home/vagrant/Code
```

　↓

```
sites:
- map: homestead.app
 to: /home/vagrant/Code/public
```

* [Laravel Homestead: 403 forbidden on nginx - Stack Overflow](https://stackoverflow.com/questions/24579107/laravel-homestead-403-forbidden-on-nginx)
* [【vagrant】共有フォルダのパーミッションで悩んだ話【chmodできない】 - すこしふしぎ．](http://ism1000ch.hatenablog.com/entry/2014/04/05/232935)

#### 403 エラーを解決できなかった方法

> Testing many permissions for project folder such as 777, 775 or 755 by this command: `chmod -R 777 /path/to/> my/project/`
> Adding a new .htaccess to the project root and putting this codes in it:
>
> ```.htaccess
> <IfModule mod_rewrite.c>
>     RewriteEngine on
>     RewriteCond %{REQUEST_URI} !^public
>     RewriteRule ^(.*)$ public/$1 [L]
> </IfModule>
> ```
>
> Change server.php to index.php and move /public/.htaccess to root of the project.

[Laravel - Forbidden You don't have permission to access - Stack Overflow](https://stackoverflow.com/questions/18272557/laravel-forbidden-you-dont-have-permission-to-access-on-this-server)

#### パーミッションの参考

> WebサーバーはOSやLinuxディストリビューションにより決められた、「Webサーバー」用のユーザーが実行ユーザーです。たとえば、Laravelと仲良しのUbuntuではwww-dataが使われています。
>
> Laravalがフレームワークとしてファイルを操作する必要がある場所は限定されています。storage下に存在するディレクトリーとbootstrap/cacheディレクトリーに「Webサーバーのユーザーから書き込みOK」というパーミッションを与える必要があります。storage下には通常、app、framework、logsの３つのディレクトリーがあります。これらのディレクトリーをWebサーバーの実行ユーザーから書き込み可能にしてください。
>
> [Laravel、デモ画面までに行き着かなかったら](https://kore1server.com/338/Laravel)


#### エラー Cannot create bind mount from...doesn't exist の解決法


```
homestead-7: Cannot create bind mount from '/Users/taku_n/code' to '/home/vagrant/code': Source path '/Users/taku_n/code' doesn't exist
```

Vagrant の仕様で同期するフォルダに似た名前を付けた時に発生するらしい。解決法は以下。エラーが出ても使えるため未検証。  

[vagrant - Cannot create bind mount destination path '/var/www' is already a bindfs mount - Stack Overflow](https://stackoverflow.com/questions/41895598/cannot-create-bind-mount-destination-path-var-www-is-already-a-bindfs-mount)

```
/abc/this_dir_too
/abc/this_dir
```

これはエラーが出て

```
/abc/this_dir
/abc/this_dir_too
```

これはうまくいくらしい


メモ
-------------------------------------------------------------

* Homestead Vagrant box のアップデート
  `vagrant box update`
* Homestead.yaml に複数プロジェクトを設定している場合、vagrant share での box 共有はできない。 その場合は、Homestead の share コマンドで切り分ける。`vagrant ssh` で仮想サーバーにログインした状態で、`share homestead.test` (homestead.test はシェアしたいもの sites.map)
* デフォルトで natdnshostresolver (OSのDNS設定へのアクセスを許可) は on になっている。
無効にしたいなら Homestead.yaml に以下を追記

```
provider: virtualbox
natdnshostresolver: off
```

* `php artisan -V` or `php artisan --version` Laravel のバージョンを確認
* `php artisan list` 使用可能な全コマンドリストを表示
* `php artisan help __migrate__` コマンドのヘルプ(例は migrate)

* Laravel だけでスケジュール(cron)実行できる

### （NFS でなく rsync を使う場合のみ）共有フォルダの同期設定

* ローカルマシン(Host)側に無いファイルが、仮想マシン(VM側)から削除されるのを回避
* 特定のファイルを同期させない (node_modules とか)

Vagrant デフォルトは `["--verbose", "--archive", "--delete", "-z", "--copy-links"]` で、 --delete があるので、転送先にないファイルは削除される。なのでこれを無効にする

参考：[RSync - Synced Folders - Vagrant](https://www.vagrantup.com/docs/synced-folders/rsync.html) オプション一覧
参考：[Vagrantのrsync時にHost側に無いFileがVM側から削除されるのを回避 - Qiita](https://qiita.com/taka4sato/items/925b665f01c375a1edee)


```Homestead.yaml
folders:
    - map: ~/code
      to: /home/vagrant/code
      type: "rsync"
      options:
          rsync__args: ["--verbose", "--archive", "--copy-links", "-z"]
          rsync__exclude: ["node_modules", ".git/"]

    # 複数設定なら code/ の下に分けて適宜追加
```