Laravelの開発環境をDockerで構築する

## はじめに
最初にディレクトリを作成します。

```
mkdir laravel_app
cd laravel_app
```

### docker-compose.yml の作成
`laravel_app`ディレクトリのルートに`docker-compose.yml`という新しい名前のファイルを作成します。

```
touch docker-compose.yml
```

こちらはコンテナのビルド方法をはじめコンテナにアクセス可能なネットワークやボリュームまで、アプリケーションの設定で作成するコンテナのすべての設定が保持されます。

`docker-compose.yml`に以下を記述します。

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

services:
```

## データベースコンテナをビルドする
`docker-compose.yml`で*services*エントリを以下のように更新します。
```yaml:docker-compose.yml
services:
    db:
        image: mysql:8.0.18
        container_name: "sample_db"
        volumes:
            - ./docker/mysql/conf.d:/etc/mysql/conf.d
            - ./docker/mysql/data:/var/lib/mysql
        ports:
            - 3306:3306
        environment:
            MYSQL_DATABASE: sample
            MYSQL_USER: sample
            MYSQL_PASSWORD: sample
            MYSQL_ROOT_PASSWORD: root
            TZ: "Asia/Tokyo"
        command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
```

*container_name*は、Docker Composeでコンテナ実行時に名前を設定します。

*image*は、コンテナのビルド元であるブループリントをDockerに認識させることができます。今回は、データベースエンジンとしてMySQLを使用するため、mysqlを指定します。

*environment*キーは、デフォルトのデータベース名やパスワードなど、環境変数のリストを指定します。

*ports*キーを使用して、ローカル開発マシンのポートをコンテナのポートにマップし、GUIツールを使用してデータベースに接続できるようにします。
コロン(:)の左側に指定されているポートはコンピューターのポートです。右側に指定されているポートはコンテナのポートです。

### `default_authentication.cnf`の作成
```
mkdir laravel_app/docker/mysql/conf.d
cd laravel_app/docker/mysql/conf.d
touch default_authentication.cnf
```
`laravel_app/docker/mysql/conf.d/default_authentication.cnf`に以下を追加します。
```cnf:default_authentication.cnf
[mysqld]
default_authentication_plugin = mysql_native_password
```

### `laravel_app/docker/mysql/data`ディレクトリの作成
```
mkdir laravel_app/docker/mysql/data
```

## PHPとNginxをビルドする

### `Dockerfile`の作成
```
mkdir laravel_app/docker/php
cd laravel_app/docker/php
touch Dockerfile
```
`laravel_app/docker/php/Dockerfile`に以下を追加します。
```Dockkerfile:Dockerfile
FROM php:8.1-fpm
COPY php.ini /usr/local/etc/php/

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

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

ENV COMPOSER_ALLOW_SUPERUSER 1

ENV COMPOSER_HOME /composer

ENV PATH $PATH:/composer/vendor/bin

RUN composer global require "laravel/installer"

RUN curl -SL https://deb.nodesource.com/setup_14.x | bash
RUN apt-get install -y nodejs && \
  npm install -g npm@latest && \
  npm install -g @vue/cli

WORKDIR /var/www
```
PHPイメージからコンテナのための骨組みを作成することに加えて、以下を実行します。

1. Laravelが依存するPHP拡張機能をインストールします。
2. コンテナの作業ディレクトリを/var/www/に設定します。
3. Composerをインストールします。

### `php.ini`の作成
```
cd laravel_app/docker/php
touch php.ini
```
`laravel_app/docker/php/php.ini`に以下を追加します。
```ini:php.ini
date.timezone = Asia/Tokyo

log_errors = On
error_log = /dev/stderr
display_errors = Off

mbstring.language = "Japanese"
```
### `default.conf`の作成
```
mkdir laravel_app/docker/nginx
cd laravel_app/docker/nginx
touch default.conf
```
`laravel_app/docker/nginx/default.conf`に以下を追加します。
```conf:default.conf
server {
  listen 80;

  root  /var/www/public;
  index index.php;

  location / {
    try_files $uri $uri/ /index.php$is_args$args;
  }

  location ~ \.php$ {
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass   php-fpm:9000;
    fastcgi_index  index.php;
    include        fastcgi_params;
    fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param  PATH_INFO $fastcgi_path_info;
  }
}
```

次に`docker-compose.yml`を以下の通り更新します。
```yaml:docker-compose.yml
version: '3'
services:
  nginx:
    image: nginx:1.17-alpine
    container_name: "sample_nginx"
    ports:
      - "8080:80"
    volumes:
      - ./src:/var/www
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - php-fpm
  php-fpm:
    build: ./docker/php
    image: "php-fpm:latest"
    container_name: "sample_php-fpm"
    volumes:
      - ./src:/var/www
    links:
      - db
    depends_on:
      - db
  db:
    image: mysql:8.0.18
    container_name: "sample_db"
    volumes:
      - ./docker/mysql/conf.d:/etc/mysql/conf.d
      - ./docker/mysql/data:/var/lib/mysql
    ports:
      - 3306:3306
    environment:
      MYSQL_DATABASE: sample
      MYSQL_USER: sample
      MYSQL_PASSWORD: sample
      MYSQL_ROOT_PASSWORD: root
      TZ: "Asia/Tokyo"
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
```

### プロジェクトのルートディレクトリ作成

```
mkdir laravel_app/src
```

### Dockerコンテナのビルド

```
docker-compose up -d --build
```

## Laravelアプリケーションを設定する

Laravelアプリケーションを設定するために次のコマンドを実行し*sample_nginx*コンテナでコンテナを開始します。
```
docker-compose exec sample_nginx bash
```

これにより、*sample_nginx*コンテナでCLIが開きます。次のコマンドを使用し、Laravelアプリケーションを作成します。
```
composer create-project laravel/laravel .
```

完了後に、http://localhost:8080/ へ移動すると、デフォルトのLaravelのウェルカムページが表示されます。

![hello_laravel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3114665/a6fbacbf-24d7-73a3-c005-5d80c302c539.png "Hello Laravel")

また、srcディレクトリを見ると、Laravelプロジェクトファイルもそこに追加されていることが分かります。

src/.envで、以下のようにデータベースパラメーターを編集します。

```env:.env
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=database
DB_USERNAME=root
DB_PASSWORD=root
```

DockerでのLaravelの環境構築は以上です。