【簡単】Laravel11+Docker 環境構築

# はじめに
 [【超入門】20分でLaravel開発環境を爆速構築するDockerハンズオン](https://qiita.com/ucan-lab/items/56c9dc3cf2e6762672f4#docker-composeyml-%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)の記事にそってLaravel11をDockerで構築したのでメモとして残しています。

# 開発環境
- Mac(Intel)
- docker：20.10.11
- Laravel：11.20.0
- PHP： 8.2.7
- Composer：2.2.24

# 前提条件
- Dokcerインストール済み

# フォルダ構成
- 以下の構成にしています。

```
Laravel11(プロジェクト名：なんでもOK)
├── infra
│   ├── mysql
│   │   ├── Dockerfile
│   │   └── my.cnf
│   ├── nginx
│   │   └── default.conf
│   └── php
│       ├── Dockerfile
│       └── php.ini
├── docker-compose.yml
├── src
│    └── Laravelをインストールするディレクトリ
└── README.md
```

# 内容

## docker-compose.ymlを作成

- プロジェクト配下でファイルを作成する
```
touch docker-compose.yml
```

```docker-compose.yml
version: "3.9"
services:
  app:
    build: ./infra/php
    volumes:
      - ./src:/data

  web:
    image: nginx:1.20-alpine
    ports:
      - 8080:80
    volumes:
      - ./src:/data
      - ./infra/nginx/default.conf:/etc/nginx/conf.d/default.conf
    working_dir: /data
```

- version：バージョンを指定
- services配下：サービス名（なんでもOK）
- build：`Dockerfile`がある `./infra/php` ディレクトリをビルドコンテキストとして指定
- volumes：`./src `ディレクトリをappサービスのコンテナ内 `/data`へマウント


## Dockerfileを作成

- ディレクトリ作成する
```
mkdir -p infra/php
```
- Dockerfileを作成する

```
touch infra/php/Dockerfile
```

```Dockerfile

FROM php:8.2-fpm-buster

ENV COMPOSER_ALLOW_SUPERUSER=1 \
  COMPOSER_HOME=/composer

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

RUN apt-get update && \
  apt-get -y install --no-install-recommends git unzip libzip-dev libicu-dev libonig-dev && \
  apt-get clean && \
  rm -rf /var/lib/apt/lists/* && \
  docker-php-ext-install intl pdo_mysql zip bcmath

COPY ./php.ini /usr/local/etc/php/php.ini

WORKDIR /data
```
## php.iniを作成

```
touch infra/php/php.ini
```

- 文字エンコーディングとタイムゾーンなどの設定をしています。
```
default_charset = UTF-8

[Date]
date.timezone = Asia/Tokyo

[mysqlnd]
mysqlnd.collect_memory_statistics = on

[Assertion]
zend.assertions = 1

[mbstring]
mbstring.language = Japanese
```

## src ディレクトリを作成

```
 mkdir src
```

## nginxを作成

```
mkdir infra/nginx
```
```
touch infra/nginx/default.conf
```
- Laravel公式の設定からrootとfastcgi_passを変更してます。
- https://readouble.com/laravel/11.x/ja/deployment.html

```default.conf
server {
    listen 80;
    server_name example.com;
    root /data/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    index 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$ {
        fastcgi_pass app:9000;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_hide_header X-Powered-By;
    }

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


## appコンテナ起動
- ビルドして起動する

```
docker compose build
```
```
docker compose up -d
```
- 起動しているか確認

```
docker ps
 
 docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS          PORTS                  NAMES
36b3a0939cf9   nginx:1.20-alpine   "/docker-entrypoint.…"   4 seconds ago    Up 2 seconds    0.0.0.0:8080->80/tcp   laravel11-web-1
27d9fe6fe7d5   laravel11-app       "docker-php-entrypoi…"   11 minutes ago   Up 11 minutes   9000/tcp               laravel11-app-1

```
- コンテナ内にはいる

```
docker container exec -it laravel11-app-1(NAMESをいれる) bash
```

## webコンテナの確認

```
 mkdir src/public
 echo "Hello World" > src/public/index.html
 echo "<?php phpinfo();" > src/public/phpinfo.php
```
- 以下へアクセスして`Hello World`が表示されていればOK

http://localhost:8080/index.html

![スクリーンショット 2024-08-14 16.15.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/923146/740031e5-0cfc-73eb-cdfc-03534f646fee.png)

- webサーバーがappサーバーへphpを実行させ結果を返してくれることを確認

http://localhost:8080/phpinfo.php

![スクリーンショット 2024-08-14 16.23.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/923146/010b4074-e08f-8660-b416-a97e00796039.png)

- 確認用のsrc配下に作成したファイルを削除

```
rm -rf src/*
```

## Laravelをインストール

- コンテナ内に入ってインストールする

```
docker container exec -it laravel11-app-1 bash
```

```
composer create-project --prefer-dist "laravel/laravel=11.*" .
```

- Laravel11がインストールされていることを確認
```
chmod -R 777 storage bootstrap/cache
php artisan -V

# Laravel Framework 11.20.0
```

- ウェルカムページも見れていること確認

http://localhost:8080

![スクリーンショット 2024-08-14 16.38.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/923146/4bf0cc88-f7ee-4eca-7e53-cfb03e6c889c.png)

## データベース(db)コンテナ作成

- docker-compose.ymlへ追記

```docker-compose.yml
version: "3.9"
services:
  app:
    build: ./infra/php
    volumes:
      - ./src:/data

  web:
    image: nginx:1.20-alpine
    ports:
      - 8080:80
    volumes:
      - ./src:/data
      - ./infra/nginx/default.conf:/etc/nginx/conf.d/default.conf
    working_dir: /data

  # 追記
  db:
    build: ./infra/mysql
    volumes:
      - db-store:/var/lib/mysql

volumes:
  db-store:

```

## ./infra/mysql/Dockerfileを作成

```
mkdir infra/mysql
```
```
touch infra/mysql/Dockerfile
```

## infra/mysql/my.cnfを作成

```
touch infra/mysql/my.cnf
```

```my.cnf
[mysqld]
# default
skip-host-cache
skip-name-resolve
datadir = /var/lib/mysql
socket = /var/lib/mysql/mysql.sock
secure-file-priv = /var/lib/mysql-files
user = mysql

pid-file = /var/run/mysqld/mysqld.pid

# character set / collation
character_set_server = utf8mb4
collation_server = utf8mb4_ja_0900_as_cs_ks

# timezone
default-time-zone = SYSTEM
log_timestamps = SYSTEM

# Error Log
log-error = mysql-error.log

# Slow Query Log
slow_query_log = 1
slow_query_log_file = mysql-slow.log
long_query_time = 1.0
log_queries_not_using_indexes = 0

# General Log
general_log = 1
general_log_file = mysql-general.log

[mysql]
default-character-set = utf8mb4

[client]
default-character-set = utf8mb4

```

## dockerをビルド・起動する

```
docker compose build
```

```
docker compose up -d
```

- 起動したか確認
```
docker ps
```

- dbコンテナが移動しているか確認

```
docker compose exec db mysql -V

# mysql起動している
mysql  Ver 8.0.32 for Linux on x86_64 (MySQL Community Server - GPL)
```

## `src/.env` のDBを設定

```src/.env
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=phper
DB_PASSWORD=secret
```

## migration実行

- コンテナに入る

```
docker container exec -it laravel11-app-1 bash 
```

```
php artisan migrate
```

![スクリーンショット 2024-08-15 18.22.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/923146/71799032-f1d8-4691-2ac9-f258bf160fef.png)

```
composer install
```

- 問題なく動作することを確認

http://localhost:8080/


![スクリーンショット 2024-08-15 18.24.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/923146/403e6d17-0e68-f740-f07c-3f6dc81b286b.png)


- 最終的なDockerコンテナ

![スクリーンショット 2024-08-15 18.26.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/923146/4118b5a2-721e-d503-eff4-d999f00f5c0e.png)

# まとめ
簡単にDocker構築できたので、よかったら参考にしてください。

# 参考
- [【超入門】20分でLaravel開発環境を爆速構築するDockerハンズオン](https://qiita.com/ucan-lab/items/56c9dc3cf2e6762672f4#docker-composeyml-%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)
- [PHP7.4 ぼくのかんがえたさいきょうのphp.ini](https://qiita.com/ucan-lab/items/0d74378e1b9ba81699a9)
- [php.ini ディレクティブのリスト](https://arc.net/l/quote/odunvsft)
- [PHP 8.x での php.ini の設定について
](https://zenn.dev/ksh2ksk4/articles/3cb75ed89ae662c1352d)