【環境構築】Docker DesktopでLaravel10の環境を構築する。

# 最終目標
Windows上で、Docker Desktopを使用し、Laravek10の開発環境を構築します。Laravel Mixではなく、Viteを採用します。以前はフロントエンドビルドツールとして標準でLaravel Mixが使われていましたが、現在はViteが標準になっているためです。

Viteはフロントエンドの開発を高速化する一方で、Docker環境を作成する際にはMixに比べて扱いづらいというデメリットもあります。

# 開発環境

・Wondows11
・Ubunto 22.4
・Docker Desktop 20.10.22
・Docker Compose 2.15.1
・Laravel10
・PHP8.1

# ディレクトリ構造
```
chat-app-laravel
├── Dockerfile
├── docker-compose.yml
├── laravel-app
│   ├── README.md
│   ├── app
│   ├── artisan
│   ├── bootstrap
│   ├── composer.json
│   ├── composer.lock
│   ├── config
│   ├── database
│   ├── package.json
│   ├── phpunit.xml
│   ├── public
│   ├── resources
│   ├── routes
│   ├── storage
│   ├── tests
│   ├── vendor
│   └── vite.config.js
└── nginx.conf
```
# Dockerfile

Dockerfileは、PHPベースの開発環境を構築する際に必要なパッケージとツールをインストールし、ComposerやNOde.jsを利用できるようにセットアップしています。

今回は、PHP8.1の公式Dockerイメージ（php:8.1-fpm）をベースにします。
```Dockerfile:
FROM php:8.1-fpm

# 必要なパッケージのインストールとDocker PHP Extensionsのインストール
RUN apt-get update && apt-get upgrade -y && \
  apt-get install -y libpng-dev libjpeg-dev libfreetype6-dev zip git unzip && \
  docker-php-ext-configure gd --with-freetype --with-jpeg && \
  docker-php-ext-install gd pdo pdo_mysql && \
  apt-get clean && \
  rm -rf /var/lib/apt/lists/*

# Composerのインストール
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Node.jsのインストール
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - && \
  apt-get install -y nodejs npm

```
〇`apt-get update && apt-get upgrade -y`
最新のパッケージリストを取得し、すべての既存のパッケージを最新版にアップグレードします。

〇`apt-get install -y libpng-dev libjpeg-dev libfreetype6-dev zip git unzip`
画像処理に必要なパッケージをインストールします。libpng、libjpeg、libfreetype6、zip、git、unzipなどです。これらは、ライブラリやファイル操作、ソースコードの取得に使用されます。

〇`docker-php-ext-xonfigure gd --with-freetype --with-jpeg && docker-php-ext-install gd pdo pdo_mysql`
GD拡張機能を構成し、必要なライブラリ(freetypeとjpeg)を使用してGD拡張をインストールします。

pdoとpdo_mysqlもインストールされます。これらは、PHPデータベース接続に関連する機能を提供します。

〇`apt-get clean && rm -rf /var/lib/apt/lists/*`

費用なパッケージを削除し、aptのキャッシュをクリアしてイメージサイズを最小化します。

〇`RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer`
Composerをダウンロードし、実行可能なファイルとして`/usr/local/bin`にインストールします。ComposerはPHPの依存関係管理ツールです。

〇`RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - && apt-get install -y nodejs npm`
Node.jsとnpmをインストールするために、noDE.JSの公式リポジトリを追加し、Node.jsとnpmをインストールします。JavaScriptの実行やフロントエンドの開発に必要です。

# docker-compose.yml

Docker Composeは複数のDockerコンテナ(Laravelアプリケーション、Nginxウェブサーバー、MySQLデータベース)を定義し、それらの間で連携するためのツールです。

今回は以下３つのサービスを定義しています。
・app
・nginx
・mysql

```yml:
version: '3'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: laravel_app
    volumes:
      - ./laravel-app/:/var/www/laravel-app
    ports:
      - "8000:8000"
      - "9000:9000"
      - "5173:5173"
    working_dir: /var/www/laravel-app
    environment:
      - "DB_HOST=mysql"
      - "DB_PORT=3306"
      - "DB_DATABASE=laravel"
      - "DB_USERNAME=root"
      - "DB_PASSWORD=secret"
  nginx:
    image: nginx:alpine
    container_name: nginx_server
    ports:
      - "8080:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      - ./:/var/www
  mysql:
    image: mysql:5.7
    container_name: mysql_db
    environment:
      - "MYSQL_DATABASE=laravel"
      # - "MYSQL_USER=root"
      - "MYSQL_PASSWORD=secret"
      - "MYSQL_ROOT_PASSWORD=secret"
    volumes:
      - mysql_data:/var/lib/mysql

volumes:
  mysql_data:

```

〇app
・Dockerfileを使用してビルドされたコンテナ。
・`./laravel_app/`ディレクトリを`/var/www/laravel-app`にマウントし、ソースコードをホストとコンテナ間で共有します。
・ポート`8000`、`9000`、`5173`をホストのそれぞれの同じポートにマッピングし、外部からアクセス可能にします。
・Laravelアプリケーション用の環境変数を定義しています。(`DB_HOST`、`DB_PORT`、`DB_DATABASE`、`DB_USERNAME`、`DB_PASSWORD`)

〇nginx
・`nginx:alpine`イメージを使用してNginxサーバを起動します。
・ホストの8080ポートをコンテナの80ポートにマッピングし、Nginxを外部からアクセス可能にします。
・`./nginx.conf`をNginxの設定ファイルとして使用し、コンテナ内の`/etc/nginx/conf.d/default.conf`にマウントします。
・ホストのカレントディレクトリ`./`をコンテナの`/var/www`にマウントし、Nginxから静的ファイルにアクセス可能にします。

〇mysql
・`mysql:5.7`イメージを使用してMySQLサーバーを起動します。
・`MYSQL_DATABASE`、`MYSQL_PASSWORD`、`MYSQL_ROOT_PASSWORD`を環境変数として設定し、MySQLのデータベース名、パスワード、ルートパスワードを定義します。
・`mysql_data`という名前の永続化ボリュームを作成し、MySQLのデータを永続化します。


# nginx.conf

Laravelアプリケーションをホストするための基本的な設定を定義します。

Laravelアプリケーションをリバースプロキシとして動作させ、PHPリクエストをFastCGIプロセスに転送するように構成されています。

```conf:
server {
    listen 80;
    index index.php index.html;
    root /var/www/laravel-app/public;
    location / {
        proxy_pass http://app:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}
```

〇`listen 80`
Nginxがポート80でリクエストを待ち受けていることを示しています。HTTPリクエストを処理します。

〇`index index.php index html`
indexファイルの優先順位を設定しています。サイよsに`index.php`を探し、見つからない場合は`index.html`を探します。

〇`root/var/www/laravel-app/public`
リクエストされたファイルが存在しない場合のデフォルトのルートディレクトリを指定します。ここでは、Laravelアプリケーションの`public`ディレクトリを指定しています。

〇`location/{...}`
・ＵＲＬパス`/`に対する設定を定義しています。
・`proxy_pass`ディレクティブを使用して、アプリケーションサーバー(`app`コンテナ)のポート8000にリクエストを転送します。
・`location~.php${...}`
・`.php`拡張子にマッチするURLパスに対する設定を定義しています。
・FastCGIプロセスマネージャーにリクエストを渡す設定です。
・`fastogi_pass`ディレクティブを使用して、PHPリクエストを処理するためにアプリケーションサーバー(`app`コンテナ)のポート9000にリクエストを転送します。
・必要なFasrCGIパラメーターを設定して、PHPファイルを処理するための情報をNginxからFastCGIプロセスに渡します。

# Laravelプロジェクト作成

Laravelプロジェクトを作成するコマンドです。

```
docker-compose run --rm app composer create-project --prefer-dist laravel/laravel .
```

`laravel-app`フォルダが作成されます。
このフォルダ名は、`docker-compose.yml`のappサービス定義で、`working_dir`が`/var/www/laravel-app`と設定しているためです。

`working_dir`は、ホストの`laravel-app/`ディレクトリにバインドしています。


# コンテナ起動
複数のDockerコンテナを起動するコマンドを実行します。
```
docker-compose up -d
```
〇`-d`オプション
コンテナをバックグラウンドで実行します。

〇`docker-compose up -d`
カレントディレクトリ内の`docker-compose.yml`を読み込み、その中で定義された複数サービスを開始します。

# コンテナ内
Docker COmposeを使用して構築された`app`コンテナ内のLaravelアプリケーションで、Node.jsパッケージの依存関係をインストールします。
```
docker-compose exec app npm install
```
〇`docker-compose exec`
定義されたサービスないのコマンドを実行。

〇`app`
実行する対象のサービス名。

〇`npm install`
Node.jsパッケージマネージャーであるnpmを使用して、プロジェクトの依存関係をインストールします。

# Laravel実行
Laravelを起動します。
```
docker-compose exec app php artisan serve --host=0.0.0.0 --port=8000
```

以下のURLにアクセスし、無事にLaravelが立ち上がっているか確認します。
```
http://localhost:8000/
```
このような画面が表示されれば問題ありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/1360fcaf-7791-d454-c9f0-3f7db901f385.png)

# 参考記事

https://qiita.com/kenji123/items/44160aa73a3794f84d4e