Laravel9(Laravel9 / MySQL8)とDockerでの基本的な環境構築の方法

# 本記事の目的
　最近携わった受託案件で、Laravel9とDockerを使った環境構築を行ったので、その方法の振り返りと、共有を込めての記事とさせていただきます。

# 構成図
　今回は以下のように、構成を組んでみました。
![Docker構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375287/31951b6c-1914-b8c1-2405-60e3de4d7b18.png)
　ディレクトリ構成図は以下の通りです。
```
docker-sample
    ├──docker
    │    ├── app
    │    │   ├── 000-default.conf
    │    │   ├── dockerfile
    │    │   └── php.ini
　　　　　　　　│　　　　　　　　├──　db
　　　　　　　　│　　　　　　　　│   ├── data
    │    │   └── my.cnf
    │    └── phpmyadmin
    │        └── sessions
    ├──src
    ├──docker-compose.yml
```
　まず、デフォルトでは上のようなディレクトリ構成になっています。一つ一つ中身を見ていきましょう。
## 000-default.conf
　これは今回Webサーバーとして選択した「__Apache__」に関する設定ファイルです。ここにしっかりと設定しておかないと、コンテナにアクセスした際に正しく該当のアプリに辿り着けません。
```
<VirtualHost *:80>
      ServerAdmin webmaster@localhost
      # デフォルトでアクセスした時に「DocumentRoot」で設定したディレクトリ配下のindex.phpファイルを
　　　　　　　　　　　　　　　　読み込んで表示する
      DocumentRoot /var/www/html/laravel-sample/public 
      ErrorLog ${APACHE_LOG_DIR}/error.log
      CustomLog ${APACHE_LOG_DIR}/access.log combined
      # DocumentRootで設定したディレクトリ内の設定
      # AllowOverrideでは「.htaccess」ファイルで設定したものを全て有効とするもの。
      # これを書いておかないと正しくルーティングしてくれない。
      <Directory /var/www/html/laraveltokyo/public>
          AllowOverride All
      </Directory>
</VirtualHost>
```
　Apache関連のエラーで正しくルーティングができないという場合は、以下の記事が役立ちますので、ご参照ください。
* [(Docker-Laravel-apache) ルーティングができない原因と対処法](https://hara-chan.com/it/infrastructure/docker-laravel-fail-routing-without-index/#docker-laravel)
## php.ini
　これはPHPに関する設定ファイルです。タイムゾーンの設定や、文字コードの設定などを行っています。
```
[Date]
date.timezone = "Asia/Tokyo"
[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"
```
## dockerfile
　そして、dockerfileです。ここでは、記述された内容を元にdockerでコンテナを立ち上げるために必要なイメージの作成を行います。
```
FROM php:8.1-apache

# 事前に記述しておいた「php.ini」と「000-default.conf」をそれぞれコンテナ内の該当箇所にコピーして適用させる
ADD php.ini /usr/local/etc/php/
ADD 000-default.conf /etc/apache2/sites-enabled/

# composerのインストール
RUN cd /usr/bin && curl -s http://getcomposer.org/installer | php && ln -s /usr/bin/composer.phar /usr/bin/composer

# ミドルウェアのインストール
RUN apt-get update \
&& apt-get install -y \
git \
zip \
unzip \
vim \
libpng-dev \
libpq-dev \
&& docker-php-ext-install pdo_mysql

# Laravelで必要になるmodRewriteを有効化するため、mods-enabledからmods-available/rewrite.loadへのシンボリックリンクを貼る
# これをしておかないと、Laravelのリダイレクト処理が正しく行われなくなってしまう
RUN mv /etc/apache2/mods-available/rewrite.load /etc/apache2/mods-enabled
RUN /bin/sh -c a2enmod rewrite
```
## my.cnf
　これはMySQLの設定を書いてあるファイルになります。
```
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
 
[client]
default-character-set=utf8mb4
```
## docker-compose.yml
　そして、docker-compose.ymlです。ここには、必要なコンテナを作成して立ち上げるための設定などを詳細に記載してあります。よくここで、 __「dockerfile」と「docker-compose」の違いは何？__ と思われる方も多いかと思います。ざっくり言うと、「dockerfile」ではコンテナ起動に必要なイメージの作成を行います。しかし、「docker-compose.yml」では、イメージの作成に加えて、ボリュームの設定やネットワークの設定までを併せて行ってくれます。ざっくりとこのように「__作るものが違う__」と覚えておきましょう。
```
# Compose fileのバージョン指定
version: '3'

# どんなコンテナを立ち上げるかを設定
services:

  # ---------------------------------
  # laravelを動かすappコンテナ
  # ---------------------------------
  app:　　-- コンテナ名
    # どのポートを開いて繋ぐか。下記ではホストの81番ポートからコンテナの80番ポートにつなぐ
    ports:
      - "81:80"
    # dockerfileで作成したイメージを元にコンテナをビルドするということ
    build: ./docker/app
    # コンテナの名前を別途指定
    container_name: app
    # volumeの設定。ローカルの./srcディレクトリからコンテナ内のアプリへアクセスできる様になる。
    volumes:
      - ./src:/var/www/html

  # ----------------------------------
  # MySQLを動かすコンテナ
  # ----------------------------------
  db:
    # Docker HubからMySQL最新版の公式イメージをダウンロードしてくる指定
    image: mysql:8.0.30
    container_name: db

    # コンテナ内の環境変数を指定
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: db
      MYSQL_USER: user
      MYSQL_PASSWORD: pass
      TZ: 'Asia/Tokyo'

    # 起動時のコマンド
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    # MySQL設定ファイルと生成されるデータをローカル上にも同期
　　　　　　　　# これをすることで、コンテナを消してもローカル上にはデータが残る
    volumes:
      - ./docker/db/data:/var/lib/mysql
      - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf
    ports:
      - 3307:3306
  
　　　　# ----------------------------------
  # PHP MyAdminを動かすコンテナ
  # ----------------------------------
  phpmyadmin:
    # Docker Hubからイメージをダウンロード
    image: phpmyadmin/phpmyadmin:5.2.0

    # コンテナの名前
    container_name: phpmyadmin

    # コンテナと他のサービスを繋げる
    links:
      - db

    # localhost:8080 で phpmyadmin の管理画面にアクセス
    ports:
      - 8080:80

    # セッション情報をボリュームに設定することで永続化できる
    volumes:
      - ./docker/phpmyadmin/sessions:/sessions
```
# コンテナをビルド
　以下の順番でコンテナをビルドします。
```
# イメージを元にコンテナを作成
$ docker-compose build

# コンテナをバックグラウンドで起動
$ docker-compose up -d

# コンテナが立ち上がっているか確認
$ docker-compose ps

# コンテナの起動ログを見る
docker-compose logs -f コンテナ名
```
　正しくビルドされたら、以下のコマンドでappコンテナの中に入り、laravelをインストールしましょう。
# Laravel9のインストール
```
# appコンテナに入る
# -itオプションをつけないと、コマンド入力しても反応してくれない
$ docker exec -it app bash

# laravel9をインストール
$ composer create-project "laravel/laravel=9.*" laravel-sample
```
　インストールが完了すると、「__./src__」からlaravelプロジェクトを編集することができる様になります。
 
# まとめ
　今回は「Laravel × Docker」での基本的な環境構築の方法についてご紹介しました。私が実際に携わった受託案件では、 __dockerに関するエラーやlaravelそのものに関するエラーが数多く出てきました。次回の記事では実際に起きたエラーと対策をまとめた記事を書きたいと思います。__
　また、dockerの基本の理解に関しては、拙筆の以下をご参照いただけると幸いです。

* [【初心者にやさしい】Dockerというスゴイ奴をしっかりと理解する](https://qiita.com/technoship0329/items/2d5a43ac22d6200be2d7)
# 参考記事
* [Dockerに慣れながら学ぶApacheサーバの基礎](https://qiita.com/amenoyoya/items/cb8bea4315447baf7a81#docker%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E8%B5%B7%E5%8B%95)
* [(Docker-Laravel-apache) ルーティングができない原因と対処法](https://hara-chan.com/it/infrastructure/docker-laravel-fail-routing-without-index/#docker-laravel)