Docker for MacのLaravel アプリケーションのが遅い？それ、ファイルをいっぱいマウントしてるからかもです。

# はじめに

**追記 2020/4/13**
Dockerfile/docker-compose.yml/Shell Scriptを見直してGitHubにコミットしています。
詳しくはGitHubにソースをアップしてますのでコチラを確認ください。
https://github.com/tyamahori/laravel-docker-env
**追記 ここまで**

皆さんこんにちは!
[tyamahori](https://twitter.com/tyamahori)です。

普段はLaravel/PHPを利用してシステム開発しています。基本的にLocal開発環境はDocker for Macを使って構築しています。

お恥ずかしい話しながらこれまでDocker for Mac、遅いなぁ。。と思いながら開発をしていました。ただ、さすがに我慢できなくなってきたので色々と調べながらある程度速度を改善することができたので、コチラにまとめて行きたいと思います。



# 結論

## ファイルのマウントを極力少なくする！
これです。今までのLocalのDocker環境の構築に追いて、無頓着にファイルのマウントを行っていました。これは遅いわけです。。先人の知恵を参考にさせていだきました。

- [docker-composeを爆速にする](https://qiita.com/shotat/items/57d049793605ffc20135)
- [Mac + Docker + Laravel の開発環境下で、異常に遅い時は Laravel Debugbar が原因な説](https://qiita.com/acro5piano/items/f15b52550a38f1617fa8)

その他にもよくあるのがdocker-syncを導入する案。これに関してはそのとおりなのですが、docker-syncを導入しなくては行けなかったり、それ用にymlファイルなどを書かなくてはいけないので、ちょっと面倒なんですよね。。

## というわけで
Laravel プロジェクトに以下のファイルをローカルのMacにマウントしないやり方で改善ができました。

- vendorディレクトリ
- storageディレクトリ

# 実際の方法
docker-compose.yml を見てもらった方が速いかと思います。

## コードはコチラ

```docker-compose.yml
version: '3'

services:
  laravel-docker-for-mac-nginx:
    image: nginx:1.17.9
    container_name: laravel-docker-for-mac-nginx
    ports:
      - 80:80
    environment:
      TZ: Asia/Tokyo
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ../../laravel/public:/opt/laravel/public
      - storage-volume:/opt/laravel/storage #ここがポイント
    depends_on:
      - laravel-docker-for-mac-php

  laravel-docker-for-mac-php:
    build: php
    container_name: laravel-docker-for-mac-php
    volumes:
      - ../../laravel:/opt/laravel
      - vendor-volume:/opt/laravel/vendor #ここがポイント
      - storage-volume:/opt/laravel/storage #ここがポイント
      - ./php/php.ini:/usr/local/etc/php/php.ini
    working_dir: /opt/laravel
    environment:
      APP_NAME: laravel-docker-for-mac
      APP_KEY: base64:I7Rrg/XK0hG//wlbPdvURt7+VXXSDS2F+QYK3R45k/M=
      DB_CONNECTION: mysql
      DB_HOST: laravel-docker-for-mac-mysql
      DB_PORT: 3306
      DB_DATABASE: laravel
      DB_USERNAME: laravel
      DB_PASSWORD: laravel
      LOG_CHANNEL: daily
      APP_DEBUG: 'true'
      APP_ENV: local
      APP_URL: http://localhost
      TZ: Asia/Tokyo

  laravel-docker-for-mac-mysql:
    image: mysql:8.0
    container_name: laravel-docker-for-mac-mysql
    command: --default-authentication-plugin=mysql_native_password
    ports:
      - 3306:3306
    volumes:
      - db-volume:/var/lib/mysql
      - ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
    environment:
      MYSQL_USER: laravel
      MYSQL_ROOT_PASSWORD: laravel
      MYSQL_PASSWORD: laravel
      MYSQL_DATABASE: laravel
      MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
      TZ: Asia/Tokyo

volumes: #ここがポイント
  storage-volume:
    driver: local
  vendor-volume:
    driver: local
  db-volume:
    driver: local
```

ディレクトリ構成はこんな感じです。
[![Screenshot from Gyazo](https://gyazo.com/1786c11d705143a1cde6440dd2fa54d1/raw)](https://gyazo.com/1786c11d705143a1cde6440dd2fa54d1)

GitHubにソースをアップしてますのでコチラも確認ください。
https://github.com/tyamahori/laravel-docker-env

## ポイント
1. volumesを利用し、storageディレクトリとvendorディレクトリのファイル群を格納する用にしています。Macのローカルに直接マウントしないように対応しています。
2. これでDocker for Mac のスピード改善が見られます。


# 注意点あり！！
ただ単純にdocker-compose up を行い、Laravelお決まりのセットアップコマンドを行おうとするとエラーがあったり、IDE(自分の場合はPhpStorm)の補完が効かなくなったりします。ちょっとした対応が必要です。


## stroageディレクトリの扱い
上記のdocker-compose.ymlでそのまま`docker-compose up`すると、コンテナ内部のLaravelプロジェクトの中に、storageディレクトリがありません。`docker cp` コマンドを利用して、初回の立ち上げ時に storageディレクトリをコンテナ内部に作るようにしました。Laravelのcache関連のファイルやDebugbarの関連ファイルがコンテナ内で保存されるようになります。

## vendorディレクトリの扱い
PhpStormを使っている場合、ローカルにvendorディレクトリがないと補完が効いてくれません。。(`コンテナ内部のvendorディレクトリをうまく見に行く方法があれば誰か教えてください。。自分はそこまでPhpStormを使いこなせてません。。。。`)

ではどうするのか、`docker cp`コマンドを使ってコンテナ内部のvendorの中身をローカルのMacに持ってきます。`docker cp`の時間と、PhoStormが cpされたvendorディレクトリの中身を読み込む時間がどうしてもかかってしまいますが、それが終わればDocker for Macの速度が改善されます。

## でもそれをコマンド叩いてやるのめんどくさい。。
安心してください！シェルスクリプトでコマンド処理をラップしました。短いコマンドでいい感じにdocker cpをしてくれるように作り込みました。その他コマンドをいくつか作ってあります。詳細は[コチラ](https://github.com/tyamahori/laravel-docker-env/blob/master/docker/formac/formac)

# 最後に

ぜひ、お手元で試してほしいです！色々とツッコミどころあったら遠慮なくご連絡ください。

```terminal
# コピペ用
$ git clone git@github.com:tyamahori/laravel-docker-env.git
$ cd laravel-docker-env/docker/formac
$ ./formac setup
$ ./formac logs # ログを出したい人用 
$ ./formac down
```