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

https://note.com/pocke_techblog/n/n8af813848fa0

上記の記事通りにすすめて、DockerでLaravel+Apache+MySQLの開発環境を構築しましたが、パーミションのエラーが出て解決に手こずったので記録に残しておきます。

##作業環境
OS：Windows 10 Pro ver.2004
Docker：version 19.03.12, build 48a66213fe

##Dockerのインストール
Dockerのインストール方法については別記事にて解説しているので、まだインストールしていないのであれば参考にしてみてください。
[Windows 10 Pro : Dockerをインストールする](https://qiita.com/neneta0921/items/46a16003ceedf6ca448d)

##サンプルコードを準備する
###フォルダ構成
フォルダ構成は以下の通りです。

```
.
├── docker/
│   ├── app/
│   │   ├ Dockerfile
│   │   ├ php.ini # PHP設定用のファイル
│   │   └ 000-default.conf  # Apacheの設定ファイル
│   └── db/
│        ├ data/ # MySQLのデータを保存しておくディレクトリ
│        └ my.cnf  # MySQLの設定ファイル
│
├── src/ # Laravelのソースを格納するディレクトリ
└── docker-compose.yml
```

###ソースコード
####Dockerfile

```docker/app/Dockerfile
# どんなdockerイメージを利用して構築をするか
FROM php:7.4-apache

# 設定ファイルをdockerコンテナ内のPHP、Apacheに読み込ませる
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を有効化する
RUN mv /etc/apache2/mods-available/rewrite.load /etc/apache2/mods-enabled
RUN /bin/sh -c a2enmod rewrite
```

####php.ini

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

```docker/app/000-default.conf
<VirtualHost *:80>
       ServerAdmin webmaster@localhost
       DocumentRoot /var/www/html/laravelapp/public
       ErrorLog ${APACHE_LOG_DIR}/error.log
       CustomLog ${APACHE_LOG_DIR}/access.log combined
       <Directory /var/www/html/laravelapp/public>
           AllowOverride All
       </Directory>
</VirtualHost>
```

####my.cnf

```docker/db/my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
[client]
default-character-set=utf8mb4
```

####docker-compose.yml

```docker-compose.yml
# Compose fileのバージョン指定
version: '3'
# どんなコンテナを立ち上げるか
services:
 # laravelを動かすコンテナ
 app:
   # どのポートを開いて繋ぐか。下記はコンテナの80番ポートを開いて、ホストの8000番につなぐ
   ports:
     - "8000:80"
   # 先ほど作ったDockerfileを使って、コンテナをビルドするという指定
   build: ./docker/app
   # コンテナの名前を指定
   container_name: laravel_app
   # コンテナとホスト側のディレクトリを同期する場所の指定。laravelのソースが入る予定の場所
   volumes:
     - ./src:/var/www/html
 # MySQLを動かすコンテナ
 db:
   # Docker HubからMySQL5.7の公式イメージをダウンロードしてくる指定
   image: mysql:5.7
   container_name: laravel_db
   # コンテナ内の環境変数を指定。環境変数を渡すとビルド時に設定してくれるDockerイメージがあるので、利用の際はDocker Hubのサイトで確認すると良い
   environment:
     MYSQL_ROOT_PASSWORD: root
     MYSQL_DATABASE: laravel_db
     MYSQL_USER: laravel_user
     MYSQL_PASSWORD: laravel_pass
     TZ: 'Asia/Tokyo'
   # 起動時のコマンド
   command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
   # ディレクトリ同期。設定ファイルとMySQLのデータが保存される場所を同期している。コンテナは基本的に起動時に変更されてもコンテナ自体が止まるとデータが消えてしまうため、保存しておきたいものはホストマシンと同期しておく必要がある。
   volumes:
     - ./docker/db/data:/var/lib/mysql
     - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf
   ports:
     - 3306:3306
```

##開発環境を構築する
###Docker Composeでコンテナを立ち上げる
次のコマンドを実行して、Docker Composeでコンテナを立ち上げます。

```
$ docker-compose build
$ docker-compose up
```

###Laravelのプロジェクトを作成する
上記とは別の画面を立ち上げて次のコマンドを実行して、Laravelのプロジェクトを作成します。

```
$ docker exec -it laravel_app bash
$ composer create-project laravel/laravel --prefer-dist laravelapp
```

これで`http://localhost:8000` にアクセスするとLaravelの画面が立ち上がるはずですが、パーミッションのエラーが起きてしまいました。

##パーミッションのエラーを解決する
最初に以下のようなエラーメッセージが出ました。
`The stream or file "/var/www/html/laravelapp/storage/logs/laravel.log" could not be opened in append mode: failed to open stream: Permission denied`

[ここのサイト](https://github.com/BookStackApp/BookStack/issues/436)を参考に以下のコマンドを実行しました。

```
$ chmod 777 /var/www/html/laravelapp/storage/logs/laravel.log
$ chmod 775 /var/www/html/laravelapp/storage/logs/
```

すると以下のようにエラーメッセージの文言が変わりました。
`file_put_contents(/var/www/html/laravelapp/storage/framework/sessions/oI2ffP9BUcWC0llE0NEoFU09eqQyXTosSZZeq4BV): failed to open stream: Permission denied`

[ここのサイト](https://stackoverflow.com/questions/38888568/laravel-file-put-contents-failed-to-open-stream-permission-denied-for-sessio)を参考に以下のコマンドを実行しました。

```
chmod -R gu+w /var/www/html/laravelapp/storage
chmod -R guo+w /var/www/html/laravelapp/storage
cd ./laravelapp
php artisan cache:clear
```

これでパーミッションのエラーが解決して、Laravelの画面が表示されました。