Nginx PHP（laravel） MySQLのDocker環境を作る途中の話

# 概要

- Nginx PHP（laravel） MySQLの組み合わせでDocker環境を作ったので途中経過も含めてまとめてみる

# 作ったもの

- システム要件

| 項目 | 情報 | バージョン | 備考 |
| --- | --- | --- | --- |
| Webサーバー | Nginx | 1.15.6 |  |
| 言語 / フレームワーク | PHP / Laravel | 8.0 / 9 |  |
| データベース | MySQL | 8.0 |  |

# ディレクトリ構成

```
laravel9_test/
├── docker
│   ├── docker-compose.yml
│   ├── mysql
│   │   ├── db
│   │   ├── initdb.d
│   │   │   └── create_database.sql
│   │   └── my.cnf
│   ├── nginx
│   │   └── default.conf
│   └── php
│       ├── Dockerfile
│       └── php.ini
└── project
    ├── .env
    ├── app
    ├── bootstrap
    ├── config
    ├── database
    ├── lang
    ├── public
    ├── resources
    ├── routes
    ├── storage
    ├── tests
    └── vendor
```

# 完成したもの

1. docker系
    1. [https://github.com/miriwo0104/laravel9_test_docker/tree/main](https://github.com/miriwo0104/laravel9_test_docker/tree/main)
1. project系
    1. [https://github.com/miriwo0104/laravel9_test_project](https://github.com/miriwo0104/laravel9_test_project)

# 前提

1. 下記の説明で実行するコマンドをは特筆しない限り、一つ前のコマンドを実行したディレクトリと同じディレクトリで実行する。

# 方法
### 必要なディレクトリの準備

1. 任意のディレクトリで下記コマンドを実行してlaravel9_testディレクトリを作成する。

    ```terminal
    $ mkdir laravel9_test
    ```

1. 下記コマンドを実行しdockerディレクトリとprojectディレクトリをlaravel9_testディレクトリ内部に作成する。

    ```terminal
    $ mkdir laravel9_test/docker
    $ mkdir laravel9_test/project
    ```

1. 下記コマンドを実行してdockerディレクトリ内部にコンテナ用のディレクトリを作成する。

    ```terminal
    $ mkdir laravel9_test/docker/php
    $ mkdir laravel9_test/docker/nginx
    $ mkdir laravel9_test/docker/mysql
    ```

### docker-compose.ymlの記載

##### 基礎部分の記載

1. 下記コマンドを実行してdocker-compose.ymlを作成して開く。

    ```terminal
    $ vi laravel9_test/docker/docker-compose.yml
    ```

1. まずは本当に基礎になる部分だけを記載してみる。

    ```laravel9_test/docker/docker-compose.yml
    version: '3'
    services:
      php:
      
      nginx:
    
      mysql:
    ```

##### PHPコンテナの記載

1. 次にPHPのコンテナに関する情報を下記に記載する。
    1. `laravel9_test/docker/php/Dockerfile`をビルドしてコンテナにする。
    1. `laravel9_test/project`ディレクトリをPHPコンテナの`/var/www/html`に紐付ける。
1. 上記のPHPコンテナの情報をdocker-compose.ymlに記載してみる。

    ```laravel9_test/docker/docker-compose.yml
    version: '3'
    services:
      php:
        build: ./php/Dockerfile
        volumes:
          - ../project:/var/www/html
    
      nginx:
    
      mysql:
    ```

##### Nginxコンテナの記載

1. 次にNginxのコンテナに関する情報を下記に記載する。
    1. バージョン → 1.15.6
    1. 8000ポートをコンテナ内の80ポートにフォワーディング
    1. `laravel9_test/docker/nginx/default.conf`をNginxコンテナの`/etc/nginx/conf.d/default.conf`に紐付ける。
    1. `laravel9_test/project`ディレクトリをNginxコンテナの`/var/www/html`に紐付ける。
    1. NginxコンテナをPHPコンテナと紐付け
1. 上記のNginxコンテナの情報をdocker-compose.ymlに記載してみる。

    ```laravel9_test/docker/docker-compose.yml
    version: '3'
    services:
      php:
        build: ./php/Dockerfile
        volumes:
          - ../project:/var/www/html
    
      nginx:
        image: nginx:1.15.6
        ports:
          - 8000:80
        volumes:
          - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
          - ../project:/var/www/html
        depends_on:
          - php
    
      mysql:
    ```

##### MySQLコンテナの記載

1. 次にMySQLのコンテナに関する情報を下記に記載する。
    1. バージョン → 8.0
    1. 4306ポートをコンテナ内の3306ポートにフォワーディング
    1. `laravel9_test/docker/mysql/my.cnf`をMySQLコンテナの`/etc/mysql/conf.d/my.cnf`に紐付ける。
    1. `laravel9_test/docker/mysql/initdb.d`をMySQLコンテナの`/docker-entrypoint-initdb.d`に紐付ける。
    1. `laravel9_test/docker/mysql/db`をMySQLコンテナの`/var/lib/mysql`に紐付ける。
    1. MySQLのrootユーザーのパスワードをrootに設定する。
    1. MySQLのタイムゾーンを「Asia/Tokyo」に設定する。
1. 上記のMySQLコンテナの情報をdocker-compose.ymlに記載してみる。

    ```laravel9_test/docker/docker-compose.yml
    version: '3'
    services:
      php:
        build: ./php
        volumes:
          - ../project:/var/www/html
    
      nginx:
        image: nginx:1.15.6
        ports:
          - 8000:80
        volumes:
          - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
          - ../project:/var/www/html
        depends_on:
          - php
    
      mysql:
        image: mysql:8.0
        ports:
          - 4306:3306
        volumes:
          - ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
          - ./mysql/initdb.d:/docker-entrypoint-initdb.d
          - ./mysql/db:/var/lib/mysql
        environment:
          MYSQL_ROOT_PASSWORD: root
          TZ: "Asia/Tokyo"
    ```

### 各コンテナの設定ファイルの記載と設置

##### PHPのDokcerfile

1. 下記コマンドを実行してDockerfileを作成して開く。

    ```terminal
    $ vi laravel9_test/docker/php/Dockerfile
    ```

1. 次にPHPコンテナに関する細かい情報を記載する。
    1. DockerImageはphp:8.0-fpmを使用する。
    1. Dockerfileと同じ階層に存在するphp.iniをコンテナ内の`/usr/local/etc/php/`にコピーする。
    1. タイムゾーンを「Asia/Tokyo」に設定する。
    1. apt-get update実行後に下記のパッケージをインストールする。
        1. zlib1g-dev
        1. mariadb-client
        1. vim
        1. libzip-dev
        1. libfreetype6-dev
        1. libjpeg62-turbo-dev
        1. libpng-dev
    1. composer（2.2.6）をインストールする。
    1. Node.js（16）をインストールする。
    1. ワーキングディレクトリをコンテナ内の`/var/www/html`に設定する。
1. 上記のPHPコンテナの細かい情報をDockerfileに記載する。

    ```laravel9_test/docker/php/Dockerfile
    FROM php:8.0-fpm
    COPY php.ini /usr/local/etc/php/
    
    ENV TZ=Asia/Tokyo
    
    RUN apt-get update \
      && apt-get install -y zlib1g-dev mariadb-client vim libzip-dev \
         libfreetype6-dev \
         libjpeg62-turbo-dev \
         libpng-dev \
      && docker-php-ext-configure gd --with-freetype --with-jpeg \
      && docker-php-ext-install -j$(nproc) gd zip pdo_mysql
    
    #Composer install
    RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
    RUN php composer-setup.php --version=2.2.6
    RUN php -r "unlink('composer-setup.php');"
    RUN mv composer.phar /usr/local/bin/composer
    
    ENV COMPOSER_ALLOW_SUPERUSER 1
    ENV COMPOSER_HOME /composer
    ENV PATH $PATH:/composer/vendor/bin
    
    # Node.js install
    RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash -
    RUN apt-get install -y nodejs && \
        npm i -g n && \
        n 16
    RUN npm i -g --unsafe-perm node-sass
    RUN npm i -g yarn lebab
    
    WORKDIR /var/www/html
    ```

##### PHPのphp.ini

1. 下記コマンドを実行してphp.iniを作成して開く。

    ```terminal
    $ vi laravel9_test/docker/php/php.ini
    ```

1. 下記のように記載する。

    ```laravel9_test/docker/php/php.ini
    [Date]
    date.timezone = "Asia/Tokyo"
    
    [mbstring]
    mbstring.internal_encoding = "UTF-8"
    mbstring.language = "Japanese"
    ```

##### Nginxのdefault.conf

1. 下記コマンドを実行してdefault.confを作成して開く。

    ```terminal
    $ vi laravel9_test/docker/nginx/default.conf
    ```

1. 下記のように記載する。

    ```laravel9_test/docker/nginx/default.conf
    server {
        listen 80;
        root  /var/www/html/public;
        index index.php index.html;
    
        location / {
            try_files $uri $uri/ /index.php$is_args$args;
        }
    
        location ~ \.php$ {
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass php:9000;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
        }
    }
    ```

##### MySQLのmy.cnf

1. 下記コマンドを実行してmy.cnfを作成して開く。

    ```terminal
    $ vi laravel9_test/docker/mysql/my.cnf
    ```

1. 下記のように記載する。

    ```laravel9_test/docker/mysql/my.cnf
    [mysqld]
    character-set-server=utf8mb4
    
    [client]
    default-character-set=utf8mb4
    ```

##### MySQLのcreate_database.sql

1. 下記コマンドを実行してinitdb.dを作成して開く。

    ```terminal
    $ vi laravel9_test/docker/mysql/initdb.d/create_database.sql
    ```

1. 下記のように記載する。

    ```laravel9_test/docker/mysql/initdb.d/create_database.sql
    CREATE DATABASE IF NOT EXISTS laravel9_test_dev;
    ```

### laravelプロジェクトの作成

1. `laravel9_test/docker`ディレクトリに移動して下記コマンドを実行し、laravel9のプロジェクトを作成する。（コマンドの最後の`.`も忘れずに。）

    ```terminal
    $ docker-compose run php composer create-project "laravel/laravel=9.*" .
    ```

1. `laravel9_test/project`ディレクトリに移動して下記コマンドを実行して.envを開く。

    ```terminal
    $ vi .env
    ```

1. DB系の記載を下記のように記載変更する。

    ```laravel9_test/project/.env
    DB_CONNECTION=mysql
    DB_HOST=mysql
    DB_PORT=3306
    DB_DATABASE=laravel9_test_dev
    DB_USERNAME=root
    DB_PASSWORD=root
    ```

# 確認

### コンテナの起動

1. `laravel9_test/docker`ディレクトリに移動して下記コマンドを実行して各コンテナを起動する。

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

1. 下記コマンドを実行してマイグレーションを実行できる事を確認する。（「PHPのコンテナ名」には`$ docker ps`などで出力した、今回起動したPHPコンテナのnameを記載する）

    ```terminal
    $ docker-compose exec php php artisan migrate
    >Deprecated: PHP Startup: Use of mbstring.internal_encoding is deprecated in Unknown on line 0
    >Migration table created successfully.
    >Migrating: 2014_10_12_000000_create_users_table
    >Migrated:  2014_10_12_000000_create_users_table (62.84ms)
    >Migrating: 2014_10_12_100000_create_password_resets_table
    >Migrated:  2014_10_12_100000_create_password_resets_table (78.82ms)
    >Migrating: 2019_08_19_000000_create_failed_jobs_table
    >Migrated:  2019_08_19_000000_create_failed_jobs_table (68.36ms)
    >Migrating: 2019_12_14_000001_create_personal_access_tokens_table
    >Migrated:  2019_12_14_000001_create_personal_access_tokens_table (80.72ms)
    ```

1. [http://localhost:8000/](http://localhost:8000/)にアクセスして下記の様な画面が表示されれば作業は完了となる。

    ![Laravel_🔊.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/95de6562-81e1-f0d0-47d2-b461be3cc675.png)