Dockerを使ってLaravelのローカル開発環境を作る(Apache版)

[Laravel Advent Calendar 2020 - Qiita](https://qiita.com/advent-calendar/2020/laravel) の 15日目 の記事です。
昨日は @noel_kuma さんの[Linter / FormatterからLaravelへの贈り物](https://qiita.com/noel_kuma/items/41f96cd74b4f29b84c29)の記事でした！
明日は @kyoya0819 さんの[Laravel de パスワードチェッカー](https://qiita.com/kyoya0819/items/3637cd4d0e7c5d48bb23)の記事です！

## 概要

[最強のLaravel開発環境をDockerを使って構築する【新編集版】](https://qiita.com/ucan-lab/items/5fc1281cd8076c8ac9f4)

この記事の反響が多く、Apache版も作って欲しいという要望もあってので記事を書いてみました。

## 対象読者

- Laravelを愛する心の持っている方
- PHP, Linux, Git, Dockerの知識をある程度持っている方

## リポジトリ

https://github.com/ucan-lab/docker-laravel-apache

## 使い方

### A. Laravelプロジェクトの新規作成

```shell-session
$ git clone git@github.com:ucan-lab/docker-laravel-apache.git
$ cd docker-laravel-apache
$ make create-project
```

http://localhost

以上の3ステップでLaravelの新規プロジェクトの環境構築は完了です。

### A'. Laravelプロジェクトをバージョン指定して新規作成

`Makefile` のLaravelインストール部分を書き換えます。

```Makefile
    docker-compose exec app composer create-project --prefer-dist "laravel/laravel=6.*" .
```

### B. 既存のLaravelプロジェクトの環境を構築する

```shell-session
$ git clone git@github.com:ucan-lab/docker-laravel-apache.git

# Laravelプロジェクトを docker-laravel-apache/backend へクローンする
$ git clone git@github.com:laravel/laravel.git docker-laravel-apache/backend

$ cd docker-laravel-apache
$ make init
```

http://localhost

これで既存のLaravelプロジェクトの環境構築は完了です。

## コンテナ構成

```
├── web
└── db
```

web, db の2つのコンテナ構成で進めます。

### nginxとの違い

Nginxの場合は、php-fpm(アプリケーションサーバー)とコンテナを分けていました。
Apacheの場合は、mod_phpというモジュールがデフォルトでインストールされており、それがPHPを実行してくれるアプリケーションサーバーを兼ねるウェブサーバーです。

## ディレクトリ構成

```
.
├── backend # Laravelプロジェクトのルートディレクトリ
├── infra
│     └── docker
│          ├── apache
│          │   └── httpd.conf
│          ├── mysql
│          │   ├── Dockerfile
│          │   └── my.cnf
│          └── php
│              ├── Dockerfile
│              └── php.ini
├── .env.example
├── Makefile
└── docker-compose.yml
```

## nginx版との差分

※nginx版との違いはnginxのディレクトリがapacheディレクトリに変わったくらいですね🤔

- infra/docker/apache/httpd.conf
- infra/docker/php/Dockerfile
- Makefile
- docker-compose.yml

変更点に関しては、上記の4つのファイルに注目していただければ良いかなと思います。
プルリクエストで詳細な差分を確認できます。

- https://github.com/ucan-lab/docker-laravel-apache/pull/2
- https://github.com/ucan-lab/docker-laravel-apache/pull/4

## PHP のベースコンテナ

- https://hub.docker.com/_/php
- https://github.com/docker-library/php/tree/master/7.4/buster/apache

イメージタグに `php:<version>-apache` が用意されています。

## 解説など

### docker-compose.yml

```yaml
version: "3.8"
volumes:
  db-store:
services:
  web:
    build:
      context: .
      dockerfile: ./infra/docker/php/Dockerfile
    ports:
      - ${WEB_PORT:-80}:80
    volumes:
      - ./backend:/work/backend
    environment:
      - DB_CONNECTION=mysql
      - DB_HOST=db
      - DB_PORT=3306
      - DB_DATABASE=${DB_NAME:-laravel_local}
      - DB_USERNAME=${DB_USER:-phper}
      - DB_PASSWORD=${DB_PASS:-secret}

  db:
    build:
      context: .
      dockerfile: ./infra/docker/mysql/Dockerfile
    ports:
      - ${DB_PORT:-3306}:3306
    volumes:
      - db-store:/var/lib/mysql
    environment:
      - MYSQL_DATABASE=${DB_NAME:-laravel_local}
      - MYSQL_USER=${DB_USER:-phper}
      - MYSQL_PASSWORD=${DB_PASS:-secret}
      - MYSQL_ROOT_PASSWORD=${DB_PASS:-secret}
```

appとwebコンテナをまとめて、webコンテナのみになりました。
どっちにするか悩みましたけど、webコンテナにしました。

解説することないので、次へ行きます。

### infra/docker/php/Dockerfile

```Dockerfile:infra/docker/php/Dockerfile
FROM node:14-buster as node
FROM php:7.4-apache-buster
LABEL maintainer="ucan-lab <yes@u-can.pro>"
SHELL ["/bin/bash", "-oeux", "pipefail", "-c"]

# timezone environment
ENV TZ=UTC \
  # locale
  LANG=en_US.UTF-8 \
  LANGUAGE=en_US:en \
  LC_ALL=en_US.UTF-8 \
  # composer environment
  COMPOSER_ALLOW_SUPERUSER=1 \
  COMPOSER_HOME=/composer

# composer command
COPY --from=composer:2.0 /usr/bin/composer /usr/bin/composer
# node command
COPY --from=node /usr/local/bin /usr/local/bin
# npm command
COPY --from=node /usr/local/lib /usr/local/lib
# yarn command
COPY --from=node /opt /opt

RUN apt-get update && \
  apt-get -y install git libicu-dev libonig-dev libzip-dev unzip locales && \
  apt-get clean && \
  rm -rf /var/lib/apt/lists/* && \
  locale-gen en_US.UTF-8 && \
  localedef -f UTF-8 -i en_US en_US.UTF-8 && \
  a2enmod rewrite && \
  docker-php-ext-install intl pdo_mysql zip bcmath && \
  composer config -g process-timeout 3600 && \
  composer config -g repos.packagist composer https://packagist.org

COPY ./infra/docker/php/php.ini /usr/local/etc/php/php.ini
COPY ./infra/docker/apache/httpd.conf /etc/apache2/sites-available/000-default.conf

WORKDIR /work/backend
```

php, composer, nodeの3つのコンテナをマルチステージビルドして使ってます。
(phpのイメージ内にapacheも入ってます。)

nodeいらないよって場合はDockerfileから削除しちゃってください。
英語圏の方にも使ってもらえるように言語&タイムゾーンのデフォルトは英語にしてます。
実際に使うときは日本に変更してご利用ください。

`a2enmod rewrite` はApacheの[mod_rewrite](http://httpd.apache.org/docs/current/mod/mod_rewrite.html)モジュールを有効化してます。
これがないとLaravelのルーティングがうまく機能しなくなります。

### infra/docker/apache/httpd.conf

```conf:infra/docker/apache/httpd.conf
<VirtualHost *:80>
    ServerName example.com
    ServerAdmin webmaster@localhost
    DocumentRoot /work/backend/public

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    <Directory /work/backend/public>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>
```

最低限設定必要な項目だけ設定してます。