Laradockを利用してLaravelの開発環境を作る

この記事は [CODEBASE okinawa Advent Calendar 2019](https://qiita.com/advent-calendar/2019/codebase-okinawa) 2日目の記事です :coffee: 

本記事では、Laradockを使って、Laravelの開発環境を構築する手順について書こうと思います。 

普段の開発環境は、Laradockを利用していないのですが、Laravelを最近さわりはじめたという方からLaradockでの開発環境構築につまずいた（migrateに失敗する）と相談を受けた際に、サクッと解決方法を提示できなかったので、改めて自分でも触ってみてみました （PHPフレームワークLaravel Webアプリケーション開発を参考にした、と話していたので、本記事でも同じような手順で書いてみました :pray: ）

## Laradockとは

> Laradock is a full PHP development environment based on Docker.

ざっくりの説明だと、Laravelの開発環境をDockerをベースでサクッと提供してくれるものです。（詳しくは [公式のページ](http://laradock.io/) をみていただけると、わかりやすいかもです :pencil: ）

## 環境構築手順

### 前提

- Dockerがインストールされている事　　
- gitがインストールされている事

### Laradockのダウンロード

- 以下のコマンドを実行する

```
# 作業ディレクトリ作成
$ mkdir laravel_docker

# 移動
$ cd laravel_docker

# laradockをclone
$ git clone https://github.com/LaraDock/laradock.git
```

### コンテナの初期化

- 以下のコマンドを実行する


```
# laradockディレクトリに移動
$ cd laradock

# envファイルをコピー
$ cp env-example .env

# コンテナの起動 （若干時間かかる）
$ docker-compose up -d nginx mysql workspace phpmyadmin

# コンテナがちゃんと起動してるか確認
$ docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                                      NAMES
42218ff4fdeb        laradock_phpmyadmin   "/docker-entrypoint.…"   10 seconds ago      Up 8 seconds        0.0.0.0:8080->80/tcp                       laradock_phpmyadmin_1
ce8875359faa        laradock_nginx        "/bin/bash /opt/star…"   47 seconds ago      Up 9 seconds        0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   laradock_nginx_1
229e9c9b0fb9        laradock_php-fpm      "docker-php-entrypoi…"   49 seconds ago      Up 47 seconds       9000/tcp                                   laradock_php-fpm_1
3f398da51a14        laradock_workspace    "/sbin/my_init"          50 seconds ago      Up 48 seconds       0.0.0.0:2222->22/tcp                       laradock_workspace_1
761b70cc0bd2        laradock_mysql        "docker-entrypoint.s…"   51 seconds ago      Up 10 seconds       0.0.0.0:3306->3306/tcp, 33060/tcp          laradock_mysql_1
8f28241ced91        docker:dind           "dockerd-entrypoint.…"   51 seconds ago      Up 49 seconds       2375-2376/tcp                              laradock_docker-in-docker_1
```

### Laravelプロジェクトの作成

- 以下のコマンドを実行する

```
# workspaceコンテナに接続
$ docker-compose exec --user=laradock workspace bash

# Laravelプロジェクト作成
$ composer create-project laravel/laravel sampleapp --prefer-dist "6.*.*"

# コンテナから出る
$ exit
```

- laradockディレクトリの `.env` ファイルの設定を変更する

- 変更前

```
# Point to the path of your applications code on your host
APP_CODE_PATH_HOST=../
```
- 変更後

```
# Point to the path of your applications code on your host
APP_CODE_PATH_HOST=../sampleapp
```

- 変更した設定を反映させるため、コンテナを再起動させる

```
# サービスの停止
$ docker-compose stop

# サービスの起動
$ docker-compose up -d nginx mysql
```

- ブラウザから `http://localhost` にアクセスして、LaravelのWelcom画面が表示を確認できたら :ok: 

<img width="1293" alt="Laravel.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70148/b03aa6ff-9a5f-7882-d023-1612f6344239.png">


### `php artisan migrate` ができることを確認する

- エラーその１（DBに接続できてない）

```
laradock@fd5cdbe63d4b:/var/www$ php artisan migrate

   Illuminate\Database\QueryException  : SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_schema.tables where table_schema = laravel and table_name = migrations and table_type = 'BASE TABLE')

  at /var/www/vendor/laravel/framework/src/Illuminate/Database/Connection.php:665
    661|         // If an exception occurs when attempting to run a query, we'll format the error
    662|         // message to include the bindings with SQL, which will make this exception a
    663|         // lot more helpful to the developer instead of just the database's errors.
    664|         catch (Exception $e) {
  > 665|             throw new QueryException(
    666|                 $query, $this->prepareBindings($bindings), $e
    667|             );
    668|         }
    669|

  Exception trace:

  1   PDOException::("SQLSTATE[HY000] [2002] Connection refused")
      /var/www/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70

  2   PDO::__construct("mysql:host=127.0.0.1;port=3306;dbname=laravel", "root", "", [])
      /var/www/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70

  Please use the argument -v to see more details.
```

- DBに接続できてないのはlaravelの`.env`の設定ができていないっぽいので、Laradockのデフォルトの設定に合わせて修正しました

- 変更前

```
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
```

- 変更後（Laradockのデフォルトの設定に合わせる）

```
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=default
DB_USERNAME=default
DB_PASSWORD=secret
```

- 上記修正後、あらためて `php artisan migrate` すると以下のエラーが発生

- エラーその２（MySQLサーバー側で使われている認証方式がLaravel側でサポートされていないっぽい）

```
laradock@fd5cdbe63d4b:/var/www$ php artisan migrate

   Illuminate\Database\QueryException  : SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client (SQL: select * from information_schema.tables where table_schema = default and table_name = migrations and table_type = 'BASE TABLE')

  at /var/www/vendor/laravel/framework/src/Illuminate/Database/Connection.php:665
    661|         // If an exception occurs when attempting to run a query, we'll format the error
    662|         // message to include the bindings with SQL, which will make this exception a
    663|         // lot more helpful to the developer instead of just the database's errors.
    664|         catch (Exception $e) {
  > 665|             throw new QueryException(
    666|                 $query, $this->prepareBindings($bindings), $e
    667|             );
    668|         }
    669|

  Exception trace:

  1   PDOException::("PDO::__construct(): The server requested authentication method unknown to the client [caching_sha2_password]")
      /var/www/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70

  2   PDO::__construct("mysql:host=mysql;port=3306;dbname=default", "default", "secret", [])
      /var/www/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70

  Please use the argument -v to see more details.
```

- MySQLユーザに対する認証方式を変更する

```
$ docker exec -it laradock_mysql_1 sh
# mysql -uroot -proot -A
mysql> alter user 'default'@'%' identified with mysql_native_password by 'secret';
```

- laradockの`mysql/my.cnf`を修正する（`default_authentication_plugin=mysql_native_password`を追加する）

```
# The MySQL  Client configuration file.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html

[mysql]

[mysqld]
sql-mode="STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
character-set-server=utf8
default_authentication_plugin=mysql_native_password // ⬅️追加

```

- 上記修正した後にあらためて `php artisan migrate` する。うまくいったのでこれで大丈夫そう :ok: 

```
laradock@fd5cdbe63d4b:/var/www$ php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (0.07 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (0.04 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (0.02 seconds)
```

### まとめ

- 今までLaradockを使ったことなかったけど、Laravelの環境構築すぐできて便利 :pencil: 
- いろんなものが入ってるので、わかりにくところは多そう
- 困ってる方の質問を受けた時にサクッとこれぐらいこたえれれるようにがんばろ :muscle: 


## 参考

- [PHPフレームワークLaravel Webアプリケーション開発バージョン 5\.5 LTS対応（竹澤 有貴、栗生 和明、新原 雅司、大村 創太郎） \| 書籍 本 \| ソシム](https://www.socym.co.jp/book/1184)

- [【Docker】LaradockでMySQL8\.0\.4にLaravelから接続する \- KM Tech Diary](https://canon1ky.hatenablog.com/entry/2018/12/16/224604)


- [Laradockはどんな経緯で作られて、何が駄目なのか? \- Endo Tech Blog](https://www.fendo181.me/entry/whats-wrong-with-laradock)