[PHP8]LaravelのDocker開発環境を構築する

# 概要
Laravel×Docker環境を作成する事になったので、自身のメモついでに書いていきます。

# 構成
Nginx, php-fpm, MySQL, Docker, Docker Composeの環境構築します。
※今回は最小限の構成で作成するので、必要に応じて修正してください。

最終的には下記のようなディレクトリ構成になります。

```
|── app
|   |── Http
|   └── ...etc
├── docker
│   ├── app
│   │   ├── Dockerfile
│   │   └── conf
│   │       └── app.ini
│   └── nginx
│       └── conf
│           └── nginx.conf
└── docker-compose.yml
```

# 各種バージョン
PHP 8.0.9
Mysql 8.0
Nginx 1.21.1
Laravel 8.54





# docker/app/Dockerfile
最終的にECSで稼働させる事を前提としていたため、イメージはalpineを使用しています。

```docker
FROM php:8.0.9-fpm-alpine

RUN apk add --no-cache freetype libpng libjpeg-turbo freetype-dev libpng-dev libjpeg-turbo-dev && \
  docker-php-ext-configure gd -with-jpeg=/usr/include/ --with-freetype=/usr/include/ && \
  NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
  docker-php-ext-install -j${NPROC} gd pdo_mysql && \
  apk del --no-cache freetype-dev libpng-dev libjpeg-turbo-dev

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

RUN { \
  echo 'access.format = "%R - %u %t \"%m %{REQUEST_URI}e\" %s"'; \
} >> /usr/local/etc/php-fpm.d/www.conf

WORKDIR /var/www/work

```

# docker/app/conf/app.ini
必要に応じて追記

```
post_max_size = 256M
short_open_tag = On
fastcgi.logging = 1
```

# docker/nginx/conf/nginx.conf
```nginx
access_log /dev/stdout main;
error_log /dev/stderr warn;

server {
    listen 80;
    root /var/www/work/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    index index.html index.htm index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        if ($request_uri ~* "^(.*/)index\.php$") {
            return 301 $1;
        }
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root/$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}
```

# docker-compose.yml
```yaml
version: '3.9'

services:
  nginx:
    image: nginx:1.21.1-alpine
    ports:
      - 80:80
    volumes:
      - ./docker/nginx/conf/nginx.conf:/etc/nginx/conf.d/default.conf
      - ./public:/var/www/work/public
    depends_on:
      - app
  app:
    build:
      context: .
      dockerfile: ./docker/app/Dockerfile
    volumes:
      - .:/var/www/work
      - ./docker/app/conf/app.ini:/usr/local/etc/php/conf.d/app.ini
    depends_on:
      - db
  db:
    image: mysql:8.0
    ports:
      - 3306:3306
    environment:
      MYSQL_DATABASE: laravel
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: root
    volumes:
      - db-volume:/var/lib/mysql
volumes:
  db-volume:

```

# コンテナ起動
```
docker-compose up -d
```

### ※初回のみ

```
docker-compose exec app php artisan key:generate
```

# 一旦確認
コンテナ起動後に`http://localhost`にアクセスして、以下のような画面が表示されていればOKです。
![スクリーンショット 2021-08-22 19.45.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600827/c0572807-9d7b-be8a-b0ce-72ad122ad534.png)

# DBとの接続

### .envを編集する
作成したdocker環境でDBに接続させるため、 `DB_HOST`と`DB_PASSWORD`を書き換えます。
本記事の通りに作成している場合は、以下の用になっていれば大丈夫です。

```.env
DB_HOST=db
DB_PASSWORD=root
```

### 接続の確認
1 マイグレーションを実行する

```
# プロジェクトのrootディレクトリで以下のコマンドを実行
docker-compose exec app php artisan migrate
```

usersテーブルにデータを挿入し、Controller経由で挿入したデータが取得できる事を確認します。
2 対話シェル(artisan thinker)を用いて適当なユーザーデータを作成します。


```
# プロジェクトのrootディレクトリで以下のコマンドを実行
docker-compose exec app php artisan tinker

# 対話シェルが開始されるので、ユーザーを作成する
App\Models\User::create(['name' => 'docker', 'email' => 'laravel_test@example.com', 'password' => bcrypt('laravel')]);
# 成功すれば、以下のように結果が出力されます。
=> App\Models\User {#4324
     name: "docker",
     email: "laravel_test@example.com",
     #password: "$2y$10$6C.yh0KtblYJWZEUgBrV8eFfzuTCZAPuZ0dGkjvUjYaXcbfUb4yz2",
     updated_at: "2021-09-04 08:53:12",
     created_at: "2021-09-04 08:53:12",
     id: 1,
   }

# 対話シェルを終了する
quit
```

3 Controllerの作成
適当なコントローラーを作成します。

```
docker-compose exec app php artisan make:controller PhotoController --resource
```

ルーティングを設定するために`routes/web.php`に下記を追加

```php
use App\Http\Controllers\PhotoController;
Route::resource('photos', PhotoController::class);
```

4 PhotoController.phpにデバッグを仕込む
`app/Http/Controllers/PhotoController.php`を開き、以下のように修正する

```php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\User;

class PhotoController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        // debug用に挿入
        dd(User::first());
    }
}
```

5 DB接続の確認
ブラウザで`http://localhost/photos`にアクセスして、以下のように登録したデータがデバッグ表示されていればDBとの接続確認完了です。
![スクリーンショット 2021-09-04 17.40.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600827/266f1017-272d-8094-0061-a619bd94670b.png)

# 最後に
今回はかなりシンプルに最低限動作する環境をDockerを用いて構築してみました。
実際の開発時には必要なモジュールや設定を適宜追加して開発を進めて頂ければと思います。