docker-composeでLaravel開発環境を構築する ~②nginx・PHPコンテナとLaravelプロジェクトの作成~

# はじめに
業務で`Laravel`の開発環境を`docker-compose`で構築することがありました。
しかし詳しいことは全く知らなかったので、自分で1から作ってみようと思います。

環境は`WEB(nginx)`、`PHP`、`DB(MySQL)`サーバーの構成となります。

今回は目次の
3、4、5についてです。
1、2に関しては[こちら](https://qiita.com/yun-yzrh/items/2d5b24d9df30624ab6d2)をご覧ください。

# 目次
　1. [docker-compose.ymlについて](https://qiita.com/yun-yzrh/items/2d5b24d9df30624ab6d2#docker-composeyml%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6:~:text=%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%AE%E4%BD%9C%E6%88%90-,docker%2Dcompose.yml%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6,-docker%2Dcompose%E3%81%A7)
　2. [必要なディレクトリ、ファイルの準備](https://qiita.com/yun-yzrh/items/2d5b24d9df30624ab6d2#docker-composeyml%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6:~:text=%E5%86%8D%E5%88%A9%E7%94%A8%E3%81%A7%E3%81%8D%E3%82%8B-,%E5%BF%85%E8%A6%81%E3%81%AA%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%80%81%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E6%BA%96%E5%82%99,-%E3%81%A7%E3%81%AF%E3%80%81%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89)
　3. [nginxコンテナの作成](#nginxコンテナの作成)　　→ 今回はここから
　4. [PHPコンテナの作成](#phpコンテナの作成) 
　5. [Laravelプロジェクトの作成](#laravelプロジェクトの作成)　　→ 今回はここまで
　6. MySQLコンテナの作成
　
# nginxコンテナの作成
それでは、`nginx`コンテナの作成をしていきます。
前回作成した`web`ディレクトリ配下にある、`Dockerfile`と`default.conf`に書き込みを行い、それに伴い`docker-compose.yml`にもコンテナについて定義していきます。
```
laravel
└── docker
    ├── docker-compose.yml --> 書き込み
    ├── web
    │   ├── Dockerfile  　　--> 書き込み
    │   └── default.conf　　--> 書き込み
    └── php
    │   ├── Dockerfile
    │   ├── php.ini
    └── db
        ├── Dockerfile
        └── my.conf
```

### 1. nginxの設定ファイルdefault.confの作成
設定ファイルは[laravel公式ドキュメント](https://readouble.com/laravel/9.x/ja/deployment.html#:~:text=%E3%82%B5%E3%83%BC%E3%83%90%E8%A8%AD%E5%AE%9A-,Nginx,-Nginx%E3%82%92%E5%AE%9F%E8%A1%8C)を参考にしました。
```~/laravel/docker/web/default.conf
server {
    # サーバが待ち受けるポートの指定
    listen 80;
    listen [::]:80;
    # ルートディレクトリの指定
    root /var/www/html/public;

    # ヘッダーの追加
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    # indexディレクティブの指定
    index index.php;

    # 文字コードの指定
    charset utf-8;

    # URIのパス毎の指定
    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; }

    location ~ \.php$ {
        fastcgi_pass php:9000; 
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

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

    # 404エラーが起きた際のページの指定
    error_page 404 /index.php;
}
```
### 2. Dockerfileの作成
コンテナ作成に必要な`Dockerfile`を作成します。
```~/laravel/docker/web/Dockerfile
# ベースイメージの指定
# FROM <イメージ>:<タグ>
FROM nginx:stable-alpine

# 作成した設定ファイルをnginxコンテナの設定ファイルにコピー
# COPY <コピー元> <コピー先>
COPY ./web/default.conf /etc/nginx/conf.d/default.conf
```
### 3. docker-compose.ymlの作成
上で作成したファイルを元に`docker-compose.yml`に`nginx`コンテナを定義します。
```~/laravel/docker/docker-compose.yml
# docker-composeのバージョン
version: "3" 

# コンテナの定義
services:
  # nginxコンテナ
  web:
    # コンテナ名
    container_name: "web"
    # コンテナ作成に使用するDockerfileのパス
    build:
      dockerfile: "./web/Dockerfile"
    # ホストとコンテナのポート番号の対応付け
    # <ホスト側のポート>:<コンテナ側のポート>
    ports:
      - "8080:80"
    # volumeをバインド
    # <ホスト側のパス>:<コンテナ側のパス>
    # srcは後ほど作成するlaravelプロジェクト
    volumes:
      - "../src:/var/www/html"
```
以上で`nginx`コンテナを起動する準備ができました。
コマンドで起動をします。
```
$ cd docker
$ docker compose up -d --build
```
以下のとおり正常に起動したのを確認し、[http://localhost:8080](http://localhost:8080)にアクセスしてみましょう。
```
[+] Running 2/2
 ⠿ Network docker_default  Created
 ⠿ Container web           Started
```
しかし現段階だと、**指定したroot配下にファイルがないため**エラー画面が表示されてしまいます。
一旦このまま`PHP`コンテナの作成に進みたいと思います。

# PHPコンテナの作成
`nginx`コンテナと同様に、`Dockerfile`と`php.ini`に書き込みを行い、
`docker-compose.yml`にもコンテナについて定義していきます。
```
laravel
└── docker
    ├── docker-compose.yml --> 書き込み
    ├── web
    │   ├── Dockerfile
    │   └── default.conf
    └── php
    │   ├── Dockerfile  　　--> 書き込み
    │   ├── php.ini　     　--> 書き込み
    └── db
        ├── Dockerfile
        └── my.conf
```

### 1. PHPの設定ファイルphp.iniの作成
タイムゾーンと言語の設定を定義します。
```~/laravel/docker/php/php.ini
# タイムゾーンの指定
[Date]
date.timezone = "Asia/Tokyo"
# 言語の指定
[mbstring]
mbstring.language = "Japanese"
```
### 2. Dockerfileの作成
コンテナ作成に必要な`Dockerfile`を作成します。
```~/laravel/docker/php/Dockerfile
# ベースイメージの指定
FROM php:fpm-buster

# 作成した設定ファイルをphpコンテナの設定ファイルにコピー
COPY ./php/php.ini /usr/local/etc/php/php.ini

# コンテナ内で作業する際のカレントディレクトリの指定
WORKDIR /var/www/html
```
### 3. docker-compose.ymlの作成
上で作成したファイルを元に`docker-compose.yml`に`PHP`コンテナを定義します。
```~/laravel/docker/docker-compose.yml
# docker-composeのバージョン
version: "3" 

# コンテナの定義
services:
  # nginxコンテナ
  web:
    ### 省略 ###
  # PHPコンテナ
  php:
    # コンテナ名
    container_name: "php"
    # コンテナ作成に使用するDockerfileのパス
    build:
      dockerfile: "./php/Dockerfile"
    # volumeをバインド
    volumes:
      - "../src:/var/www/html"
```
以上で`PHP`コンテナを起動する準備ができました。
コマンドで起動をします。
```
$ docker compose up -d --build
```
以下のとおり正常に起動したのを確認できました。
```
[+] Running 3/3
 ⠿ Network docker_default  Created
 ⠿ Container php           Started
 ⠿ Container web           Started
```

# Laravelプロジェクトの作成
`Laravel`プロジェクトを作成するには、`composer`や`pdo_mysql`など各種インストールが必要です。
`Dockerfile`にインストールする内容を記載し、イメージ構築時に必要なものをインストールするようにします。

### 1. Dockerfileの修正
既存の`Dockerfile`にインストールする命令を追記します。
```~/laravel/docker/php/Dockerfile
# ベースイメージの指定
FROM php:fpm-buster

# 作成した設定ファイルをphpコンテナの設定ファイルにコピー
COPY ./php/php.ini /usr/local/etc/php/php.ini

# パッケージのインストール
RUN apt-get update \
    && apt-get -y install git zip unzip vim

RUN docker-php-ext-install pdo_mysql

# composerのインストール
RUN cd /usr/bin && curl -s http://getcomposer.org/installer | php && ln -s /usr/bin/composer.phar /usr/bin/composer

# コンテナ内で作業する際のカレントディレクトリの指定
WORKDIR /var/www/html
```
### 2. Laravelプロジェクトの作成
上記でインストールした内容を反映させるために再度コンテナを起動します。
```
$ docker compose up -d --build
```
正常に起動したのを確認し、`PHP`コンテナ内で`Laravel`プロジェクトを作成します。
```
$ docker compose exec php bash
$ composer create-project --prefer-dist "laravel/laravel=" .
```
カレントディレクトリは`PHP`の`Dockerfile`で指定した`/var/www/html`となり
`nginx`の`Dockerfile`で指定したルート`/var/www/html/public`は、作成した`Laravel`プロジェクトの`public`ディレクトリ配下を指します。
改めて[http://localhost:8080](http://localhost:8080)にアクセスしてみましょう。
![スクリーンショット 2023-04-17 9.30.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192385/449646f2-b04e-c6bc-31c1-e7d832cce63e.png)
`Laravel`の画面が確認できました。
ここまででフォルダ構成は以下のようになります。
```
laravel
└── docker
    ├── docker-compose.yml
    ├── web
    │   ├── Dockerfile
    │   └── default.conf
    └── php
    │   ├── Dockerfile
    │   ├── php.ini
    └── db
        ├── Dockerfile
        └── my.conf
├── src  -->laraveプロジェクト
```

# まとめ
今回は`nginx`と`PHP`のコンテナ作成、`Laravel`プロジェクトの作成まで行いました！
次は`DB(MySQL)`コンテナを作成していきます！

# 参考
https://zenn.dev/naoyuki42/articles/ae215286ba92b2