laravel+dockerの環境構築で詰まった原因

##はじめに

タイトルの通り、初学者が独学でdocker+laravelの環境構築を行なった際に詰まった点をメモとして記録します。
非常に初歩的な記事になりますので、プログラミング初学者の方向けと思ってください。


##環境

Docker version 20.10.2
docker-compose version 1.27.4
laravel 7.30.4

##構成
以下の構成で組み立てました。

todoapp
├ docker-compose.yml
├ docker
│　 ├ php
│ 　│　 ├ php.ini
│ 　│ 　└ Dockerfile
│　 └ nginx
│ 　　　└ default.conf
└ server

##環境構築の手順

###1. ディレクトリ作成
まず、デスクトップに任意のディレクトリを作成します。今回はtodoappというディレクトリ名で進めました。
その直下に、ディレクトリとしてdocker, serverを作成します。また、新規ファイルとしてdocker-compose.ymlを作成します。
Laravelプロジェクトはserver直下に作成します。

###2. docker-compose.ymlへの記述

PHP, nginx, mysqlの３つのコンテナを想定し、以下のように記述します。

```php:docker-compose.yml

version: '3'

services:
  php:
    container_name: php
    build: ./docker/php
    volumes:
    - ./server:/var/www

  nginx:
    image: nginx
    container_name: nginx
    ports:
    - 80:80
    volumes:
    - ./server:/var/www
    - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
    - php

  db:
    image: mysql:5.7
    container_name: db-host
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: database
      MYSQL_USER: docker
      MYSQL_PASSWORD: docker
      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
```

###3. Dockerfile作成
phpコンテナ構築時に使われるDockerfileをdocker/php/に作成します。

```php:Dockerfile

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

RUN apt-get update \
  && apt-get install -y zlib1g-dev mariadb-client \
  && docker-php-ext-install zip pdo_mysql

#Composer install
COPY --from=composer /usr/bin/composer /usr/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"
```

###4. php.ini作成
phpの設定ファイルであるphp.iniを、Dockerfile同様にdocker/php/に作成します。
記述は最低限の設定にしているため、その他設定したい項目があったら随時記述してください。

```php:php.ini

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

###5. default.conf作成
nginxの設定ファイルであるdefault.confファイルを、docker/nginx/に作成します。

```php:default.conf

server {
  listen 80;
    index index.php index.html;
    root /var/www/public;

  location / {
    root /var/www/public;
    index  index.html index.php;
    try_files $uri $uri/ /index.php?$query_string;
    }

  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;
  }
 }
```

###6. Laravelプロジェクト作成
ここまでで、Laravelプロジェクトを動かすために必要なファイルの作成は完了です。
docker-compose.ymlがあるディレクトリ(todoapp)に移動して下記でdockerを起動してみましょう。
その後dockerに入って、Laravelプロジェクトを作成します。

```

# docker起動
$ docker-compose up -d

# phpコンテナに入ります
$ docker-compose exec php bash

# Laravelプロジェクト作成
root@1740893368a8:/var/www# composer create-project laravel/laravel
```

上記を実行後、serverディレクトリ以下にlaravelの各ディレクトリやファイルが作成されています。

###7. 動作確認
ブラウザからlocalhostにアクセスしてみましょう。

![](404 Not Found)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1119751/0f414475-224f-fe61-ef24-c8dcb3849ee6.png)


、、、ん？Laravelが表示されない、、
しかし、もしポートが間違っていた場合やdockerが起動していない場合は、'このサイトにアクセスできません'と書かれた画面が表示されるはずなので、dockerコンテナの動作はしている模様。

###※修正
画面にも表示されているように、nginxに関するエラーの予感。
ということで現段階で唯一nginx直下にあるファイルである、default.confを再度見直してみる。

```php:default.conf

server {
  listen 80;
    index index.php index.html;
    root /var/www/public;

  location / {
    root /var/www/public;
    index  index.html index.php;
    try_files $uri $uri/ /index.php?$query_string;
    }
```
ポート番号80番を読み込ませているし、一見問題ないように見えるコードですが、、見つけました。
root /var/www/public/;は公開するディレクトリの宣言をしています。しかしよく考えると、/wwwと/publicを中継するものがあるはずです。
ということで、以下に書き換えて実行してみました。

```php:default.conf

server {
  listen 80;
    index index.php index.html;
    root /var/www/laravel/public;

  location / {
    root /var/www/laravel/public;
    index  index.html index.php;
    try_files $uri $uri/ /index.php?$query_string;
    }

  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;
  }
 }
```

また、index index.php index.html;はリクエストuriが/で終わっている時にインデックスとして返されるファイルを表しています。index.phpが存在すればindex.phpを返し、存在しなければindex.htmlを返します。どちらも存在しない場合のリダイレクト先を設定したい場合は、index index.php index.html /ファイルがどちらもない場合のリダイレクト先;のようにします。

###◎結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1119751/4887b9ee-d236-4ce1-57d0-442e83d8da27.png)

無事に表示することに成功しました。

###8. MySQLとの接続
mysqlコンテナに入り、接続できれば完了。

```

# mysqlコンテナに入る
$ docker exec -it db-host bash
root@4a125a55d12a:/# mysql -u root -p
Enter password: パスワードを入力する
mysql> 
#上記の表示がでたら接続完了
```

envファイルを修正(docker-compose.ymlの内容に合わせる)

```php:.env

DB_CONNECTION=mysql
DB_HOST=db-host
DB_PORT=3306
DB_DATABASE=[docker-composeで定義したデータベース名]
DB_USERNAME=[docker-composeで定義したユーザ名]
DB_PASSWORD=[docker-composeで定義したパスワード名]
```

マイグレーション
todoapp上で、docker-compose exec php bashを叩きコンテナ内へ入った後、

```:root@4a125a55d12a：/var/www/laravel#

php artisan migrate
```

※うまくいかなければ、以下を試す。
・php artisan cache:clear

##まとめ
以上でlaravel+dockerの環境構築は完了です。
nginxの機能をいまいち理解できていないまま進めていくと壁にあたりますね、、
ここからlaravelで様々な機能を実装していこうと思うので、またそれぞれでメモを残していきます！