Laravelのローカル環境をDockerを利用してSSLからLaravel Duskの設定まで

## 環境

- Docker for Mac
- Laravel5.5
- Nginx
- PHP-FPM
- MySQL5.7

## 最終的なディレクトリ構造

```
docker-laravel/
├── docker-config/
|   ├── docker-compose.yml
│   ├── nginx
│   │    ├── cert-key
│   │    └── nginx.conf
│　　└── php-fpm
│        └── Dockerfile
└── laravel(Laravelのディレクトリ)
```

## 最終的な`docker-laravel/docker-config/docker-compose.yml`

```yml
version: '3'
services: 
  nginx:
    image: nginx:alpine
    depends_on: 
      - php-fpm
    ports:
      - 80:80
      - 443:443
    volumes:
      - ../:/var/www/html
      - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
      - ./nginx/cert-key:/etc/nginx/ssl
  php-fpm:
    build: ./php-fpm
    depends_on: 
      - mysql
    ports:
      - 9000:9000
    volumes:
      - ../laravel:/var/www/html
  mysql:
    image: mysql:5.7
    ports:
      - 3306:3306
    environment:
      - MYSQL_USER=root
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_DATABASE=sample
    volumes: 
      - ./data-mysql:/var/lib/mysql
    container_name: mysql57
  selenium:
    image: selenium/standalone-chrome-debug
    ports: 
      - 4444:4444
      - 5900:5900
    depends_on: 
      - nginx
    privileged: true
    container_name: selenium
```

## 最初の`docker-laravel/docker-config/docker-compose.yml`
```yml
version: '3'
services: 
  nginx:
    image: nginx:alpine
    depends_on: 
      - php-fpm
    ports:
      - 80:80
      - 443:443
    volumes:
      - ../:/var/www/html
      - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
      - ./nginx/cert-key:/etc/nginx/ssl
  php-fpm:
    build: ./php-fpm
    ports:
      - 9000:9000
    volumes:
      - ../:/var/www/html
```

## 操作
まず`docker-laravel`のディレクトリ内でdocker-configディレクトリを作成し、`最初のdocker-compose.yml`・nginxディレクトリ・php-fpmディレクトリを作成する。

`docker-laravel/docker-config/nginx/nginx.conf`を以下の通りに作成


```conf
#nginx.conf

server {
    listen 80;
    server_name localhost;

    return 301 https://$host$request_uri;
}

server {
    listen 443;
    server_name localhost;
    
    root  /var/www/html;
    index index.php;

    ssl on;
    access_log /var/log/nginx/access.log;
    error_log  /var/log/nginx/error.log;

    ssl_certificate /etc/nginx/ssl/localhost+1.pem;
    ssl_certificate_key //etc/nginx/ssl/localhost+1-key.pem;
 
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }
 
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(\.+)$;
        fastcgi_pass php-fpm:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}
```

`docker-laravel/docker-config/php-fpm`ディレクトリで`Dockerfile`を以下の通りに作成する。

```dockerfile
FROM php:fpm-alpine

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer 

RUN docker-php-ext-install mysqli && \
    docker-php-ext-install pdo_mysql
    
RUN apk add --update nodejs nodejs-npm

RUN apk add --no-cache \
    build-base \
    libpng-dev \
    lcms2-dev \
    bash
```

### mkcertのインストール
以下の操作をmacのターミナルで実行

```sh
brew install mkcert
mkcert -install
mkcert localhost 127.0.0.1
```
作成された`localhost+1.pem` `localhost+1-key.pem` を`docker-laravel/docker-config/nginx/cert-key`に配置する。

### docker-composeのbuild

`docker-laravel/docker-config/`ディレクトリ以下の操作を実行しLaravelをインストールする

```sh
docker-compose build
docker-compose up -d
docker-compose exec php-fpm bash
# php-fpm コンテナ内
composer create-project "laravel/laravel=5.5.*" laravel
cd laravel
chmod 777 storage -R
php artisan key:generate
```

最終的な`docker-laravel/docker-config/docker-compose.yml`通りに`docker-compose.yml`を編集

再度以下の通りの操作を実行する

```sh
docker-compose up -d
docker-compose exec php-fpm bash
```
ここで[https://localhost](https://localhost)にアクセスするとLaravelのデフォルト画面が開く。

### .envの編集

`docker-laravel/laravel/.env`を以下の通りに編集する。

```
#.env

APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_LOG_LEVEL=debug
APP_URL=https://localhost

DB_CONNECTION=mysql
DB_HOST=mysql57
DB_PORT=3306
DB_DATABASE=root
DB_USERNAME=password
DB_PASSWORD=sample

BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
```

編集が完了したらば

```sh
# php-fpm コンテナ内
php artisan migrate
```
でmigrationができることを確認する。
エラーが出る場合はキャッシュが残っている可能性があるので、キャッシュを消す

```sh
# php-fpm コンテナ内
php artisan config:clear
```

### npmを使いたい場合

以下の操作を実行し、JSファイルをコンパイルする。

```sh
# php-fpm コンテナ内
npm install
npm run dev
```

### Laravel Duskの起動

Laravel Duskを使う場合、以下の操作を実行

```sh
# php-fpm コンテナ内
composer require --dev laravel/dusk:"^2.0"
php artisan dusk:install
```

`docker-laravel/laravel/tests/DuskTestCase.php`を以下の通りに編集。

```php

<?php

namespace Tests;

use Laravel\Dusk\TestCase as BaseTestCase;
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;

abstract class DuskTestCase extends BaseTestCase
{
    use CreatesApplication;

    /**
     * Prepare for Dusk test execution.
     *
     * @beforeClass
     * @return void
     */
    public static function prepare()
    {
        // static::startChromeDriver();
    }
    /*
    *
     * Create the RemoteWebDriver instance.
     *
     * @return \Facebook\WebDriver\Remote\RemoteWebDriver
     */
    protected function driver()
    {
        $options = (new ChromeOptions)->addArguments([
            '--disable-gpu',
            // '--headless'
        ]);

        return RemoteWebDriver::create(
            'http://selenium:4444/wd/hub', DesiredCapabilities::chrome()->setCapability(
                ChromeOptions::CAPABILITY, $options
            )
        );
    }
}

```

編集が完了したらば

```sh
# php-fpm コンテナ内
php artisan dusk
```

でLaravel Duskを起動する。起動状況が見たい場合は

- Finderを起動
- 移動タグを選択
- サーバーへ接続を選択
- サーバーアドレスにvnc://localhost:5900を入力
- Passwordにsecretを入力

の操作を行うことで起動状況が見れる。

## 参考
[docker-codeception-example](https://github.com/imunew/docker-codeception-example)
[Laravel Dusk日本語公式ドキュメント](https://readouble.com/laravel/5.5/ja/dusk.html)
[mkcertを使ってローカル環境でもDockerでも楽々SSL](https://qiita.com/ProjectEuropa/items/37b0cfbe0d2347d8e16a)
[Dockerでサクっとローカル開発環境(LAMP + Laravel)を構築する](https://qiita.com/ProjectEuropa/items/5fbb00848cd8d5b57182)