ハマりを回避してDockerでLaravel6系環境構築

## 執筆の経緯
- [前回の記事](https://qiita.com/2san/items/662a2b90fc8a94fa9a62)が結構見てもらえて、Qiita執筆の味を占めたから。
- 自分がハマりまくったので、これはハマり回避できる環境構築記事を書かねばという使命感を感じたから。

## 想定読者
- [前回の記事](https://qiita.com/2san/items/662a2b90fc8a94fa9a62)を理解している方。
    - 前回の記事の構成をLaravel用に編集する形で環境構築します。

## 今回のゴール
- DockerでLaravelの環境構築を行い、welcomeページを拝む。

## 実行環境と筆者のレベル感
### 実行環境
- PC : MacBookAir(M1, 2020)
- OS : macOS Big Sur11.4
- チップ : Apple M1
- メモリ : 16GB
- DockerDesktop : 3.5.2
- Docker ： 20.10.7

### 筆者のレベル感
- 2021年10月から勤務開始した新米エンジニア。
フロント担当なので、バックエンドは疎いです。
ともに育ちましょう。 

## ファイル構成

```
.
├── docker
│   ├── mysql
│   │   ├── Dockerfile
│   │   ├── my.cnf
│   │   └── data
│   └── php
│       ├── 000-default.conf
│       └── Dockerfile
├── docker-compose.yml
└── src
    ├── backend
    └── frontend
```

## ステップ１　PHPのDockerfileを修正&apacheの設定ファイルを作成する

```:Dockerfile
FROM php:7.3-apache

COPY ./000-default.conf /etc/apache2/sites-available/000-default.conf

COPY --from=composer:2.0 /usr/bin/composer /usr/bin/composer

RUN apt-get update  \
    && apt-get -y install \
    git \
    zip \
    unzip \
    vim \
    && docker-php-ext-install pdo_mysql bcmath mbstring \
    && a2enmod rewrite
    
WORKDIR /var/www/html

EXPOSE 80
```

```000-default.conf
<VirtualHost *:80>
	ServerAdmin webmaster@localhost
	DocumentRoot /var/www/html

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined
	<Directory /var/www/html>
		AllowOverride All
		Options Indexes FollowSymLinks
		Require all granted
	</Directory>

</VirtualHost>
```

### ３行目 ※以下全てPHPのDockerfileの行数です。
- apacheの設定ファイルをホスト（自分のパソコン）からコンテナ内にコピーする。
    - これを設定しておかないとLaravelのルーティング機能が使用できない。致命的なので設定必須。
    - 参考文献の[『(Docker-Laravel-apache) ルーティングができない原因と対処法』](https://hara-chan.com/it/infrastructure/docker-laravel-fail-routing-without-index/)にとても助けられました。

### ５行目
- composerをインストールする。
    - Dockerのバージョンが17.05以上である必要があります。
    - 参考文献[『Docker に Composer をインストールするベストプラクティス（と解説）』](https://qiita.com/yatsbashy/items/02bbbebbfe7e5a5976bc)参照。

### ９〜１２行目
- 以前はインストールしていなかったパッケージたちです。
何故インストールしたかはとても簡単で、composerでLaravelプロジェクトを作成しようとしたところ、「こいつらをインストールしろ」とcomposerに怒られたからです笑
    - gitとvimはいいとして、zipとunzipはファイルの圧縮・解凍を行うライブラリのようです。名前のまんまですね。

### １４行目
- これも先ほどの[『(Docker-Laravel-apache) ルーティングができない原因と対処法』](https://hara-chan.com/it/infrastructure/docker-laravel-fail-routing-without-index/)に助けられました。
    - こちらもLaravelのルーティング機能が使用できなくなるので、設定必須です。

## ステップ２　MySQLのDockerfileを修正する

```:Dockerfile
FROM --platform=linux/x86_64 mysql:8.0

COPY ./my.cnf /etc/mysql/conf.d/my.cnf

EXPOSE 3306
```

```my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
explicit-defaults-for-timestamp=1
general-log=1
general-log-file=/var/log/mysql/mysqld.log

[client]
default-character-set=utf8mb4
```

### １行目 ※以下全てMySQLのDockerfileの行数です。
- 前回はWindows機で試してましたが、今回はM1Macなので、それ用のFROM命令に変えています。
参考文献[『M1 MacでDockerを使った開発環境構築にハマった』](https://fixel.co.jp/blog/docker-m1mac/)参照。
intelMacの場合は「mysql:8.0」の記載だけで動くはず。

### ３行目
- データベース内での文字化けを防ぐため、charasetを設定。
    - この辺り正直詳しくは分かっていない。参考文献『Dockerの公式MySQLの文字コードをutf8mb4に設定する』のコピペで済ませてしまっている。

## ステップ３　docker-compose.ymlを修正する 

```docker-compose.yml
version: '3'
services:
  backend:
    build:
      context: ./docker/php
      dockerfile: Dockerfile
    ports:
      - "80:80"
    volumes:
      - ./src/backend:/var/www/html
    depends_on:
      - db

  db:
    build:
      context: ./docker/mysql
      dockerfile: Dockerfile
    command: --default-authentication-plugin=mysql_native_password
    ports:
      - "3306:3306"
    volumes:
      - ./docker/mysql/data:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=pass
```

### １８行目
- MySQLのパスワードの認証方法を「mysql_native_password」に変更しています。
    - 今回はMySQLを用いた動作検証しませんが、どうせつまるポイントなので書いておきます。
    - Mysql8系から「caching_sha2_password」というセキュリティ性の高い認証方法が導入されましたが、各種ライブラリやソフトが対応していないケースがあるため、変更しています。
    - ちなみにPHPは7.2.4からcaching_sha2_password」に対応しているようですが、今回PHP7.3を使用していますが、何故かここを変更しないとLaravelからdbへ接続できませんでした。

## 動作確認
### Laravelのwelcomeページを拝む。
- まずはイメージのbuildとコンテナの立ち上げ。2〜3分かかります。
    - Dockerfileの設定を変えた場合はその都度buildが必要です。

```
$ docker compose build
$ docker compose up -d
```

- 念の為インストールされているかどうかPHPとcomposerのバージョン確認をしておきましょう。

```
$ docker compose exec backend bash
root@123456789123:/var/www/html# php -v

PHP 7.3.32 (cli) (built: Oct 28 2021 17:01:17) ( NTS )
// 省略

root@123456789123:/var/www/html# composer -V

Composer version 2.0.14 2021-05-21 17:03:37
```

- いよいよLaravelをインストールします。
    - コマンドの意味はカレントディレクトリにlaravel6系をインストールしてねという意味です。
 src/backend内にファイルが作成されていくはずです。
    - 最後の「.」を何か単語に変えればその名前のディレクトリにプロジェクトが作成されます。
 src/backend配下に指定したディレクトリが作成されます。

```
root@123456789123:/var/www/html# composer create-project --prefer-dist "laravel/laravel=6.*" .
```

- http\://localhost/public/にアクセス。以下の画面になれば無事成功。
    - LaravelはpublicがルートのURL。
![スクリーンショット 2021-11-06 23.39.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/973482/4c4846e6-d6f2-5474-e599-cf4a0049c3e6.png)

## 次回予告
- Laravelで実際にCRUD処理をやってみたいと思います。

## 参考文献
今回も多くのサイトおよび記事を参考にさせていただきました。
ありがとうございます！
[・(Docker-Laravel-apache) ルーティングができない原因と対処法](https://hara-chan.com/it/infrastructure/docker-laravel-fail-routing-without-index/)
[・Apacheのmod_rewrite設定メモ](https://qiita.com/Y-Kanoh/items/42af3c2f635653c4eaf7)
[・M1 MacでDockerを使った開発環境構築にハマった](https://fixel.co.jp/blog/docker-m1mac/)
[・MySQL8.0 認証方式を変更する(Laravel5)](https://qiita.com/ucan-lab/items/3ae911b7e13287a5b917)
[・Docker に Composer をインストールするベストプラクティス（と解説）](https://qiita.com/yatsbashy/items/02bbbebbfe7e5a5976bc)
[・【後編】絶対に失敗しないDockerでLaravel + Vue.jsの開発環境（LEMP環境）を構築する方法〜MacOS Intel Chip対応〜](https://yutaro-blog.net/2021/04/30/docker-laravel-vuejs-3/)
[・Laravelをcomposerでインストールする方法](https://zenn.dev/akido_/articles/4ab86fa3046a27)
[・composer の–prefer-distってよく使うけど何してる？](https://kin29.info/composer-%E3%81%AE-prefer-dist%E3%81%A3%E3%81%A6%E3%82%88%E3%81%8F%E4%BD%BF%E3%81%86%E3%81%91%E3%81%A9%E4%BD%95%E3%81%97%E3%81%A6%E3%82%8B%EF%BC%9F/)
[・【初心者向け】Laravelで419エラーが発生してPOSTできないとき](https://poppotennis.com/posts/laravel-419-error#third)
[・Dockerの公式MySQLの文字コードをutf8mb4に設定する](https://qiita.com/Suzuki09/items/c05664c7c0c08a19cebe)