Laravel×Docker挙動を軽くする方法_修正版

## 作成背景
- 以前書いた記事が情報不足でわかりづらいため補足する

## サンプルプロジェクト

https://github.com/koinunopochi/larabel-docker_sample/tree/master

最終形態を載せたプロジェクトを置いておくので適宜参照してほしい

## 以前の記事

https://qiita.com/koinunopochi/items/8f749b29973a9d46bacc

## 最新版

https://qiita.com/koinunopochi/items/5240c121b3ac69835acd


## Laravelが重くなる原因
`/var/www/html/storage/framework`と`/var/www/html/vendor`が悪さをしているため、ローカルフォルダにマウントしないことで解決する

## 一筋縄でいかない理由
単純に事前に、マウントを外せばよいと考え実行すると、Laravelを`src`ディレクトリにインストールしようとしたタイミングでディレクトリが空でないとエラーが出てしまう、、

フォルダをDockerイメージ作成時にマウントしないようにすると`src`ディレクトリに空のディレクトリが作成されてしまうのが原因である

:::note warn
おそらく、srcに作成されている`/var/www/html/storage/framework`と`/var/www/html/vendor`のボリューム先を別の場所に指定することができれば一度で解決するはず、、？
:::

自分のDocker習熟度が低いため今回は、Laravelを導入した後に改めてイメージをビルドしなおして修正する方法を取ろうと思う

## 作業実施

### 手順１-Dockerfile, compose.yamlの作成

https://github.com/koinunopochi/larabel-docker_sample/tree/master

まずはこのレポジトリから、`container`ディレクトリ配下すべてと`compose.yaml`を取得してください。

:::note info
今回主に編集するのは`compose.yaml`になりますがバージョンの変更やほかに必要なもののインストール、`MySQL`から`PostgreSQL`への変更など適宜必要に応じて改変してご利用ください。
:::

### 手順2-compsoe.yamlの変更
現在の`compose.yaml`は通常実行用のものとなっているため、新しいプロジェクトを作成する場合には`compose.aml`を修正する必要があります。

:::note info
試していないですがローカルディレクトリでLaravelをインストールして、新たにビルドすれば問題なく現在の`compose.yaml`でも問題なく実行が可能なはずです
:::

変更点は2つです。

```yaml:compose.yaml
  # PHPサーバー
  php:
    # コンテナ名
    container_name: "php"
    # コンテナの作成に使用するDockerfileのパス
    build:
      dockerfile: "./container/php/Dockerfile"
    # srcディレクトリ内のファイルをコンテナ内の~/var/www/html配下にマウント
    volumes:
      - ./src:/var/www/html
      # - storage-volumes:/var/www/html/storage/framework
      # - vendor-volumes:/var/www/html/vendor
```

```yaml:compose.yaml
# volumes: 
  # storage-volumes:
  # vendor-volumes:
```

<details><summary>Laravelインストール前用_完全版</summary>

```yaml:compose.yaml
# コンテナ定義
services:
  # webサーバー
  web:
    # コンテナ名
    container_name: "web"
    # コンテナの作成に使用するDockerfileのパス
    build:
      dockerfile: "./container/web/Dockerfile"
    # ホスト側のポート:コンテナ側のポートを指定
    ports:
      - "8080:80"
    # src配下のファイルをコンテナ内の~/va/www/html配下に配置
    volumes:
      - "./src:/var/www/html"

  # PHPサーバー
  php:
    # コンテナ名
    container_name: "php"
    # コンテナの作成に使用するDockerfileのパス
    build:
      dockerfile: "./container/php/Dockerfile"
    # srcディレクトリ内のファイルをコンテナ内の~/var/www/html配下にマウント
    volumes:
      - ./src:/var/www/html
      # - storage-volumes:/var/www/html/storage/framework
      # - vendor-volumes:/var/www/html/vendor

  # DBサーバー
  db:
    # コンテナ名
    container_name: "db"
    # コンテナの作成に使用するDockerfileのパス
    build:
      dockerfile: "./container/db/Dockerfile"
    # ホスト側のポート:コンテナ側のポートを指定
    ports:
      - "3306:3306"
    # 環境変数の指定
    environment:
      - "MYSQL_ROOT_PASSWORD=password"
      - "MYSQL_DATABASE=database"
      - "MYSQL_USER=laravel"
      - "MYSQL_PASSWORD=password"
    # srcディレクトリ内のファイルをコンテナ内の~/var/www/html配下にマウント
    volumes:
      - "./container/db/data:/var/lib/mysql"
# volumes: 
#   storage-volumes:
#   vendor-volumes:
```
</details>

### 手順3-ビルド
```sh
docker compose up -d
```

### 手順4-Laravelのインストール
Laravelをインストールします。
```sh
docker-compose exec php composer create-project --prefer-dist "laravel/laravel=10.*" .
```
少し待ち時間が長いですが、気長に待ちましょう。

### 手順5-compose.yamlの修正
先ほどコメントアウトした部分を戻します。
<details><summary>修正</summary>

```yaml:compose.yaml
# コンテナ定義
services:
  # webサーバー
  web:
    # コンテナ名
    container_name: "web"
    # コンテナの作成に使用するDockerfileのパス
    build:
      dockerfile: "./container/web/Dockerfile"
    # ホスト側のポート:コンテナ側のポートを指定
    ports:
      - "8080:80"
    # src配下のファイルをコンテナ内の~/va/www/html配下に配置
    volumes:
      - "./src:/var/www/html"

  # PHPサーバー
  php:
    # コンテナ名
    container_name: "php"
    # コンテナの作成に使用するDockerfileのパス
    build:
      dockerfile: "./container/php/Dockerfile"
    # srcディレクトリ内のファイルをコンテナ内の~/var/www/html配下にマウント
    volumes:
      - ./src:/var/www/html
      - storage-volumes:/var/www/html/storage/framework
      - vendor-volumes:/var/www/html/vendor

  # DBサーバー
  db:
    # コンテナ名
    container_name: "db"
    # コンテナの作成に使用するDockerfileのパス
    build:
      dockerfile: "./container/db/Dockerfile"
    # ホスト側のポート:コンテナ側のポートを指定
    ports:
      - "3306:3306"
    # 環境変数の指定
    environment:
      - "MYSQL_ROOT_PASSWORD=password"
      - "MYSQL_DATABASE=database"
      - "MYSQL_USER=laravel"
      - "MYSQL_PASSWORD=password"
    # srcディレクトリ内のファイルをコンテナ内の~/var/www/html配下にマウント
    volumes:
      - "./container/db/data:/var/lib/mysql"
volumes: 
  storage-volumes:
  vendor-volumes:
```
</details>

### 手順6-リビルドする
今の状態は、先ほど説明した原因部分も併せてマウントしてしまっているため、動作が軽くなるように再度ビルドし直します。
```sh
docker compose build
docker compose up -d
```

### 手順7-マウントしないことで起こるエラーを解決する

http://localhost:8080

にアクセスすることでエラーを確認できます。
今回の場合は、以下のようになっているはずです。
```sh:error
Warning: require(/var/www/html/public/../vendor/autoload.php): Failed to open stream: No such file or directory in /var/www/html/public/index.php on line 34

Fatal error: Uncaught Error: Failed opening required '/var/www/html/public/../vendor/autoload.php' (include_path='.:/usr/local/lib/php') in /var/www/html/public/index.php:34 Stack trace: #0 {main} thrown in /var/www/html/public/index.php on line 34
```

ファイルがないと怒っているので、ファイルをコピーすることで解決します。
```sh
# PHPコンテナのIDを取得します
docker container ls
```
次のようにコピーします。
```sh
# idは適宜変更してください。
docker cp ./src/vendor cdd242978d2e:/var/www/html
docker cp ./src/storage cdd242978d2e:/var/www/html
```

### 手順8-アクセス権の設定

http://localhost:8080

もう一度アクセスすると今度は、権限エラーが発生していることが分かります


```sh:error
file_put_contents(/var/www/html/storage/framework/sessions/iKVv2XjaoEEY8msML26fhhGBCwh9mKqG4VnFPGjS): Failed to open stream: No such file or directory
```
:::note warn
ファイルやディレクトリがないと言っていますが、実際には`権限エラー`となっています。
気になる方は、ディレクトリが実際にあるかを確認してください。
:::

:::note alert
今回は開発環境なので、`フル権限`を与えていますが実際に運用する場合は最低限必要なだけの権限を与えるようにしてください。
:::

```sh
docker-compose exec php chmod -R 777 /var/www/html/storage
```

### 手順9-起動確認
最後に、dockerを落とした場合でも再度起動できるかを確認します

```sh
docker-compose down
docker-compose up -d
```

http://localhost:8080

アクセスしたところ、正常に起動しない場合はyamlファイルの修正を行いビルドし直したあたりから再度やってみると解決が速いでしょう。

## まとめ
以前の記事が分かりづらくあったので、今回改めてわかりやすくプロジェクトを立ち上げやすくなるように修正した。

実際のところ現在指定したバージョンのPHPやLaravelを利用するのであれば、[GitHub](https://github.com/koinunopochi/larabel-docker_sample/tree/master)から引っ張るだけでよいので、以前よりもずいぶんと楽にLaravelプロジェクトを始めることができるようになったと思う。