Dockerでnginx＋MySQL＋Laravelの環境構築からプロジェクト作成・DBへのマイグレーションまで

##概要
タイトル通りの環境構築、その上でのプロジェクトの作成までの流れを記事にしてみます。初投稿なのでお手柔らかに、、

この構成だとlaradockと同じなのですが、今回は1から作ります。
##用意する環境
・PHP7.2
(GDライブラリも)
・MySQL8.0
・nginx1.15

##前提
Dockerがインストールされている

##初期フォルダ構成
laravel-project
　├ docker
　│　　└ nginx
　│　　│　　└ default.conf
　│　　└ php
　│　　　　└ Dockerfile
　│　　　　└ php.ini　
　│ 　　 
　└ docker-compose.yml
　│　　
　└ server
　
##docker-compose.yml
まずコンテナ情報書きます。

```ruby:docker-compose.yml
version: '3'

services:
  nginx:
    image: nginx
    container_name: web
    ports:
    - 80:80
    volumes:
    - ./server:/var/www
    - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
    - php
    links:
    - php
  
  php:
    container_name: app
    build: ./docker/php
    volumes:
    - ./server:/var/www
    depends_on:
    - mysql
    links:
    - mysql

  mysql:
    image: mysql:5.7
    container_name: mysql
    hostname: mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: db
      MYSQL_USER: root
      MYSQL_PASSWORD: root
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    volumes:
    - ./docker/db/data:/var/lib/mysql
    - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf
    - ./docker/db/sql:/docker-entrypoint-initdb.d
    ports:
    - 3306:3306
```
nginxはビルドしないでイメージそのまま使ってます。
mysqlにhostname(ホスト名)を指定します。mysqlの接続に苦労して、たどり着いたのがこの方法。
コンテナ名は指定しなくてもいいのですがあとでわかりやすくなるのでつけました。

##Dockerfile
次にPHPの情報を書きます。docker-compose.ymlで指定したビルドのフォルダー内のDockerfileを参照してイメージが作られるのですよね。

```ruby:Dockerfile
FROM php:7.2-fpm
COPY php.ini /usr/local/etc/php/

RUN apt-get update \
  && apt-get install -y \
    gcc \
    make \
    libpng-dev \
    git \
    unzip \
    vim \
    libmcrypt-dev \
    mysql-client \
    curl \
    gnupg \
    libjpeg-dev \
    libfreetype6-dev \
    && docker-php-ext-install zip pdo_mysql \
    && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
    && docker-php-ext-install -j$(nproc) gd

#Composer install
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
RUN php -r "if (hash_file('sha384', 'composer-setup.php') === '48e3236262b34d30969dca3c37281b3b4bbe3221bda826ac6a9a62d6444cdb0dcd0615698a5cbe587c3f0fe57a54d8f5') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
RUN php composer-setup.php
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


WORKDIR /var/www

RUN composer global require "laravel/installer"
```
composerも一緒にインストールしてしまいます。

またこの記事では触れませんが今回作成するプロジェクトで画像圧縮をしたいので以下の行でGDライブラリもインストールしています。

```
&& docker-php-ext-install -j$(nproc) gd
```
##php.ini
phpの情報。

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

##nginx
nginxのファイルを作ります。このあと、beerという名前のプロジェクトを作るので、ルートの記述を変えておきます。
自分で作るときは自分のプロジェクト名にルートを変えてください。

```ruby:default.conf
server {
  listen 80;
    index index.php index.html;
    root /var/www/beer/public;

  location / {
    root /var/www/beer/public;
    index  index.html index.php;
    }

  location ~ \.php$ {

    try_files $uri =404;
    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;
  }
 }
```
nginxまだ読み解けてないので細部まで理解したら別記事で紹介したいなぁ、、

##コンテナを立ち上げる
ここまでできたらターミナルで作業ディレクトリに移動し、以下のコマンドを叩きます。


```
$docker-compose up -d　--build    //コンテナの立ち上げ
```
うまくコンテナが立ち上がれば以下のコマンドで稼働してるコンテナが表示されます。

```
$docker ps  
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                               NAMES
d7cdf858638e        nginx                 "nginx -g 'daemon of…"   3 hours ago         Up 44 minutes       0.0.0.0:80->80/tcp                  web
5fe07c818f30        laravel-project_php   "docker-php-entrypoi…"   3 hours ago         Up 44 minutes       9000/tcp                            app
4e16f632634a        mysql:5.7             "docker-entrypoint.s…"   3 hours ago         Up 44 minutes       0.0.0.0:3306->3306/tcp, 33060/tcp   mysql
```
ちなみに`$docker ps -q`でコンテナのIDだけ見ることもできます。

次に、laravelでプロジェクトを作りたいので、PHPのコンテナに入ります。コンテナに入るときは

```
$docker exec -it [コンテナのID or コンテナ名] sh
```
とします。

コンテナに入ったらプロジェクトを作成し、作成したプロジェクトのディレクトリに移動します。
laravel newはちょっと時間かかります。

```
$docker exec -it app sh
#laravel new プロジェクト名(ここではbeer)
#cd beer
```
この段階でディレクトリは以下のようになってるはずです。

laravel-project
　├ docker
　│　　└ nginx
　│　　│　　└ default.conf
　│　　└ php
　│　　│　└ Dockerfile
　│　　│　└ php.ini　 　　 
　│　　└ db
　│ 
　└ docker-compose.yml
　│　　
　└ server
　　　　└ beer　

##データベースに接続できるようにする
プロジェクトの中の.envファイルを編集してデータベースに接続できるようにします。以下のように書きます。

```ruby:.env

DB_CONNECTION=mysql
DB_DRIVER=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=db
DB_USERNAME=root
DB_PASSWORD=root
```
このときDB_HOSTがlocalhostや127.0.0.1だと接続が拒否されてしまう可能性があります。おそらくコンテナ内のMySQLのホストがlocalhostじゃないからなのかな？
またSQLSTATE[HY000] [2054] The server requested authentication method unknown to the clientというエラーが出たこともあった。調べたけど解決できなくて今のファイル構成に落ち着きました。

##マイグレーションする
ここまでやっておけばエラーもなくマイグレーションできるはず。先ほど入ったコンテナの中でそのまま以下のコマンドを叩きます。

```
#php artisan db:seed
#php artisan migrate
```
password_resets,usersの2つのテーブルがマイグレーションされます。
データベースの方でテーブルが作成されて入れば完璧です。
こんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454650/4c52d0ad-0814-ed6b-c81d-15bd3ec1a321.png)

##GDライブラリが入っているかの確認
Dockerfileで記述したGDライブラリの確認をします。
phpinfoでみます。bodyタグの直下に。

```ruby:welcome.blade.php
<body>
        <?php phpinfo() ?>
        <div class="flex-center position-ref full-height">
            @if (Route::has('login'))
```
localhostにアクセスします。

<img width="969" alt="スクリーンショット 2019-07-05 4.20.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454650/281b4988-2c02-a19d-a07a-493ce9af1557.png">

やったー！

##最後に
よくある形なのでいろんな人のものを参考にさせていただきましたが、初めて自分でコンテナ構成考えてみました。自分で書くことでdockerの知識が深まりました。まだまだ弱いところが多いのでレベルアップした構成のものもいつか記事にしたいです。

##参考にさせていただいた記事

・[Dockerを使ってLaravel開発環境構築](https://qiita.com/A-Kira/items/1c55ef689c0f91420e81)
・[Laravelの開発環境をDockerを使って構築する](https://qiita.com/ucan-lab/items/17c806973e69792ada99)