Laradockを使ったlaravel開発環境

laravelを試したいために、手っ取り早い方法としてLaradockを使ってみようと思います。

## 下準備

work用のディレクトリ作成

```
% mkdir -p ~/study/laravel/laraveltest
% cd $_
% mkdir testapp
```

## laradock
docker使ってよしなに開発サーバ用意してくれるものという理解。
redisとかsolrとかnginxとかapacheとかmysqlとかphpmyadminとか用意されていて簡単にサーバを作ることができる。

今回はAPサーバとDB使ってみる

* nginx
* mysql

まずはここらへん見ながら
http://laradock.io/getting-started/

既存のプロジェクトにlaradock導入する場合こんな感じでやるといいらしい

```
└── project-a
    └── laradock-a
```

今回はイチから作ろのでこういう構成でやってみる。先にtestappディレクトリだけ作っておいた。

```
~/study/laravel/laraveltest
├── laradock
└── testapp
```

### laradockセットアップ

```
% git clone https://github.com/laradock/laradock.git
% cd laradock
```

アクセスするドメインを変更したいならconfファイルに指定するとのこと。変更しないけどデフォルトの設定、server_name、root、indexらへんは確認しておこうか

nginx/sites/default.conf

```
server {

    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    server_name localhost;
    root /var/www/public;
    index index.php index.html index.htm;

    location / {
         try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        try_files $uri /index.php =404;
        fastcgi_pass php-upstream;
        fastcgi_index index.php;
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        #fixes timeouts
        fastcgi_read_timeout 600;
        include fastcgi_params;
    }

    location ~ /\.ht {
        deny all;
    }

    location /.well-known/acme-challenge/ {
        root /var/www/letsencrypt/;
        log_not_found off;
    }
}
```

#### laradockの設定
.envファイル作成。サンプルがあるのでそれを ベースに使おう。

```
% cp env-example .env
```

この.envファイルって何？どう使われているの？
docker-compose.ymlで使われているのでしばらくするとわかると思います。

アプリケーションのディレクトリを指定。APP_CODE_PATH_HOSTをtestappに変更

```
% vi .env
#APP_CODE_PATH_HOST=../
APP_CODE_PATH_HOST=../testapp/
```

### workspaceコンテナの起動
composerやらnodeやらlaravelの開発に必要なものが入っているコンテナ。

```
% docker-compose up -d workspace
```

中身はどうなってるかというと、docker-compose.ymlをみてあげればなんとなくわかる。他に立ち上げることができるコンテナにどんなものがあるのかもわかる。

```
% cat docker-compose.yml
・・・
### Workspace Utilities ##################################
    workspace:
      build:
        context: ./workspace
        args:
          - PHP_VERSION=${PHP_VERSION}
          - INSTALL_XDEBUG=${WORKSPACE_INSTALL_XDEBUG}
          - INSTALL_BLACKFIRE=${INSTALL_BLACKFIRE}
          - INSTALL_SOAP=${WORKSPACE_INSTALL_SOAP}
          - INSTALL_LDAP=${WORKSPACE_INSTALL_LDAP}
          - INSTALL_IMAP=${WORKSPACE_INSTALL_IMAP}
          - INSTALL_MONGO=${WORKSPACE_INSTALL_MONGO}
          - INSTALL_AMQP=${WORKSPACE_INSTALL_AMQP}
          - INSTALL_PHPREDIS=${WORKSPACE_INSTALL_PHPREDIS}
          - INSTALL_MSSQL=${WORKSPACE_INSTALL_MSSQL}
          - INSTALL_NODE=${WORKSPACE_INSTALL_NODE}
          - NPM_REGISTRY=${WORKSPACE_NPM_REGISTRY}
          - INSTALL_YARN=${WORKSPACE_INSTALL_YARN}
          - INSTALL_DRUSH=${WORKSPACE_INSTALL_DRUSH}
          - INSTALL_DRUPAL_CONSOLE=${WORKSPACE_INSTALL_DRUPAL_CONSOLE}
          - INSTALL_AEROSPIKE=${WORKSPACE_INSTALL_AEROSPIKE}
          - INSTALL_V8JS=${WORKSPACE_INSTALL_V8JS}
          - COMPOSER_GLOBAL_INSTALL=${WORKSPACE_COMPOSER_GLOBAL_INSTALL}
          - COMPOSER_REPO_PACKAGIST=${WORKSPACE_COMPOSER_REPO_PACKAGIST}
          - INSTALL_WORKSPACE_SSH=${WORKSPACE_INSTALL_WORKSPACE_SSH}
          - INSTALL_LARAVEL_ENVOY=${WORKSPACE_INSTALL_LARAVEL_ENVOY}
          - INSTALL_LARAVEL_INSTALLER=${WORKSPACE_INSTALL_LARAVEL_INSTALLER}
          - INSTALL_DEPLOYER=${WORKSPACE_INSTALL_DEPLOYER}
          - INSTALL_PRESTISSIMO=${WORKSPACE_INSTALL_PRESTISSIMO}
          - INSTALL_LINUXBREW=${WORKSPACE_INSTALL_LINUXBREW}
          - INSTALL_MC=${WORKSPACE_INSTALL_MC}
          - INSTALL_SYMFONY=${WORKSPACE_INSTALL_SYMFONY}
          - INSTALL_PYTHON=${WORKSPACE_INSTALL_PYTHON}
          - INSTALL_IMAGE_OPTIMIZERS=${WORKSPACE_INSTALL_IMAGE_OPTIMIZERS}
          - INSTALL_IMAGEMAGICK=${WORKSPACE_INSTALL_IMAGEMAGICK}
          - INSTALL_TERRAFORM=${WORKSPACE_INSTALL_TERRAFORM}
          - INSTALL_DUSK_DEPS=${WORKSPACE_INSTALL_DUSK_DEPS}
          - INSTALL_PG_CLIENT=${WORKSPACE_INSTALL_PG_CLIENT}
          - INSTALL_SWOOLE=${WORKSPACE_INSTALL_SWOOLE}
          - PUID=${WORKSPACE_PUID}
          - PGID=${WORKSPACE_PGID}
          - CHROME_DRIVER_VERSION=${WORKSPACE_CHROME_DRIVER_VERSION}
          - NODE_VERSION=${WORKSPACE_NODE_VERSION}
          - YARN_VERSION=${WORKSPACE_YARN_VERSION}
          - TZ=${WORKSPACE_TIMEZONE}
          - BLACKFIRE_CLIENT_ID=${BLACKFIRE_CLIENT_ID}
          - BLACKFIRE_CLIENT_TOKEN=${BLACKFIRE_CLIENT_TOKEN}
          - DRUSH_VERSION=${DRUSH_VERSION}
      volumes:
        - ${APP_CODE_PATH_HOST}:${APP_CODE_PATH_CONTAINER}
      extra_hosts:
        - "dockerhost:${DOCKER_HOST_IP}"
      ports:
        - "${WORKSPACE_SSH_PORT}:22"
      tty: true
      environment:
        - PHP_IDE_CONFIG=${PHP_IDE_CONFIG}
      networks:
        - frontend
        - backend
```
volumes でコンテナのディレクトリとローカルのディレクトリの紐付けが行われている。これでコンテナ内で変更したものがローカルに。ローカルで変更したものがコンテナに反映される仕組み。

`${APP_CODE_PATH_HOST}`、`${APP_CODE_PATH_CONTAINER}`はさっきコピーした.envファイルに設定されている。APP_CODE_PATH_HOSTは先ほどtestappに変更した。

.env

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

# Point to where the `APP_CODE_PATH_HOST` should be in the container. You may add flags to the path `:cached`, `:delegated`. When using Docker Sync add `:nocopy`
APP_CODE_PATH_CONTAINER=/var/www:cached
```

### laravelプロジェクト作成
laravelの開発に必要なものがworkspaceコンテナに用意されているので、このコンテナ内で作業すればよし。


コンテナ内に入って作業

```
% docker-compose exec workspace bash
% composer create-project laravel/laravel . --prefer-dist
```

外からコンテナ上でコマンド実行でもOK

```
% docker-compose exec workspace composer create-project laravel/laravel . --prefer-dist
```

どっちでもやってることは同じ。色々やることがあれば、コンテナ内に入って作業したほうがいいけど、1コマンドだけ実行するなら、入るまでもないみたいな使いわけなのかなと。

### nginx起動して動作確認
```
% docker-compose up -d nginx
```

ブラウザでアクセス
http://localhost

![スクリーンショット 2018-05-03 16.37.01.png](https://qiita-image-store.s3.amazonaws.com/0/32503/6d1ec683-0e04-3d40-e596-04419deb0c10.png)

### mysqlへの接続
DBへの接続もできるようにしておきたいと思います。

laradockのmysqlコンテナの設定を確認しておこう。workspaceの時と同じ感じ。

laradock/docer-compose.yml

```
### MySQL ################################################
    mysql:
      build:
        context: ./mysql
        args:
          - MYSQL_VERSION=${MYSQL_VERSION}
      environment:
        - MYSQL_DATABASE=${MYSQL_DATABASE}
        - MYSQL_USER=${MYSQL_USER}
        - MYSQL_PASSWORD=${MYSQL_PASSWORD}
        - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
        - TZ=${WORKSPACE_TIMEZONE}
      volumes:
        - ${DATA_PATH_HOST}/mysql:/var/lib/mysql
        - ${MYSQL_ENTRYPOINT_INITDB}:/docker-entrypoint-initdb.d
      ports:
        - "${MYSQL_PORT}:3306"
      networks:
        - backend
```

laradock/.env

```
### MYSQL #################################################

#MYSQL_VERSION=latest
MYSQL_VERSION=5.7
MYSQL_DATABASE=default
MYSQL_USER=default
MYSQL_PASSWORD=secret
MYSQL_PORT=3306
MYSQL_ROOT_PASSWORD=root
MYSQL_ENTRYPOINT_INITDB=./mysql/docker-entrypoint-initdb.d
```

MYSQL_VERSIONだけ変更しました。

```
% docker-compose up -d mysql
Starting laradock_mysql_1 ... done
```

うまく立ち上がればこうなって、StatusのところがUpになっているはず。Exit 2とかだと起動に失敗してる。

```
% docker-compose ps
        Name                      Command              State                    Ports
-------------------------------------------------------------------------------------------------------
laradock_mysql_1       docker-entrypoint.sh mysqld     Up      0.0.0.0:3306->3306/tcp
laradock_nginx_1       nginx                           Up      0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp
laradock_php-fpm_1     docker-php-entrypoint php-fpm   Up      9000/tcp
laradock_workspace_1   /sbin/my_init                   Up      0.0.0.0:2222->22/tcp
```

### DB接続確認
migrateはlaravel使ってDBに接続してるはずなのでDB接続の確認はこれで。scaffoldみたいなのあれば簡単でいいなぁと思ったけどlaravelには標準では見つからないのでまぁできてるでしょうということで。

mysqlに接続

```
% docker-compose exec mysql mysql -uroot -proot
mysql>
```

ローカルの3306ポートに紐つけられているのでこれでもよし

```
% mysql -uroot -proot
```

プロジェクトのDB接続設定
laradockのほうじゃなくて、プロジェクトのほうの.env

```
% vi ../testapp/.env
DB_CONNECTION=mysql
#DB_HOST=127.0.0.1
DB_HOST=mysql
DB_PORT=3306
#DB_DATABASE=homestead
DB_DATABASE=default
#DB_USERNAME=homestead
DB_USERNAME=default
DB_PASSWORD=secret
```
databaseは先に作っておく必要があるみたい。面倒なのでdefault使っちゃう。

```
% docker-compose exec workspace php artisan migrate:install
% docker-compose exec workspace php artisan migrate
```

```
% mysql -uroot -proot default
mysql> show tables;
+-------------------+
| Tables_in_default |
+-------------------+
| migrations        |
| password_resets   |
| users             |
+-------------------+
3 rows in set (0.00 sec)
```

migrationされてテーブル作られているのでDB接続も問題なさそう


## mysqlが起動しないトラブルシュート

### ローカルのmysqlが起動していて3306ポートが使えない場合

```
% docker-compose up -d mysql
Starting laradock_mysql_1 ... error

ERROR: for laradock_mysql_1  Cannot start service mysql: driver failed programming external connectivity on endpoint laradock_mysql_1 (321dd76338c96fbc822eb534d47b64def13d1bcebc7899def799b0da6d7c099c): Error starting userland proxy: Bind for 0.0.0.0:3306 failed: port is already allocated

ERROR: for mysql  Cannot start service mysql: driver failed programming external connectivity on endpoint laradock_mysql_1 (321dd76338c96fbc822eb534d47b64def13d1bcebc7899def799b0da6d7c099c): Error starting userland proxy: Bind for 0.0.0.0:3306 failed: port is already allocated
ERROR: Encountered errors while bringing up the project.
```

windowsだとPermission deniedになるらしい

```
ERROR: for a9e7628e2be7_laradock_mysql_1  Cannot start service mysql: driver failed programming external connectivity on endpoint laradock_mysql_1 (bd740192b9d2ade5b32f89b90dStarting laradock_nginx_1                ... done

ERROR: for mysql  Cannot start service mysql: driver failed programming external connectivity on endpoint laradock_mysql_1 (bd740192b9d2ade5b32f89b90d09a94c506079a7d9aeb877aa1699e404303e7d): Error starting userland proxy: Bind for 0.0.0.0:3306: unexpected error Permission denied
ERROR: Encountered errors while bringing up the project.
```

### MYSQL_VERSIONをlatestのままやったら
Exit 2になってこんなエラー出てました。

```
% docker-compose logs mysql
Attaching to laradock_mysql_1
mysql_1                |
mysql_1                | ERROR: mysqld failed while attempting to check config
mysql_1                | command was: "mysqld --verbose --help"
mysql_1                |
mysql_1                | 2018-05-03T11:08:45.963958Z 0 [Warning] [MY-011070] [Server] 'Disabling symbolic links using --skip-symbolic-links (or equivalent) is the default. Consider not using this option as it' is deprecated and will be removed in a future release.
mysql_1                | 2018-05-03T11:08:45.964029Z 0 [ERROR] [MY-011071] [Server] /usr/sbin/mysqld: Error while setting value 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' to 'sql_mode'
mysql_1                | 2018-05-03T11:08:45.965497Z 0 [ERROR] [MY-010119] [Server] Aborting
```

latestのほうが意識高いよね！ってことで自分もlatest使いたがりますが、試したいだけならば5.7にするのが無難。

ちなみに、色々調べてmysqlのsql_modeが変わっててここらへんいじると動いた。

mysql/my.cnf を変更してNO_AUTO_CREATE_USER を消す。

```
# 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_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
character-set-server=utf8
```

バージョン変えたりして色々やっているとデータが壊れてしまってうまくいかないようなので、一度まっさらにして試すとうまくいったりします。

```
% docker-compose down
% rm -rf ~/.laradock/data/mysql
% docker rmi laradock_mysql -f
% docker rmi mysql -f
% docker-compose build mysql

docker image ls で見てmysqlっぽいものも全部消してみる
```
イメージの削除どこまでやればいいかわからないけど、とりあえず全部やってやった

### migrateしようとするもエラー

```
% docker-compose exec workspace php artisan migrate:install

   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)

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

  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:68

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

  Please use the argument -v to see more details.
```
mysqlコンテナ作り直したらうまくいった。

---------

そもそも、laradockでmysqlが起動しないって質問されて、ローカルでやってみたらうまくいっててdockerなのに差があるのやだなぁと思って、ちゃんとまとめておこうと思ってやりはじめたのですが、、、

ローカルでうまくいってたのは、latestが古いバージョン向いたままだったようで、latestの罠ですかね。それでもlatestをなぜか使いたくなるんですけどw

参考にしたサイト
https://qiita.com/lara_bell/items/d4bd1340a5cc7dfcfcb4
https://teratail.com/questions/122336
https://github.com/laradock/laradock/issues/1492
https://stackoverflow.com/questions/50068663/laravel-5-5-with-mysql-8-0-11-sql-mode-cant-be-set-to-the-value-of-no-auto?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
https://laravel-news.com/laravel-5-6-18
https://github.com/laradock/laradock/issues/1392