Help us understand the problem. What is going on with this article?

DockerでPHP7.4+Apache+MySQLの環境構築しようと思ったら詰まりまくった【Windows & Mac】

"はじめに"

今回はDockerをつかってLaravel+Apache+MySQLの開発環境を構築したいと思います。
初心者プログラマーを含めたチームで個人開発を行うため、基本的に導入方法や手順などは視覚的にわかりやすく、簡単なものを採用する方針です。

"Dockerの導入"

早速本題であるDockerの導入をしていきましょう。

Hyper-vの有効か(Windowsのみ

Dockerのインストール前にHyper-vという仮想化機能を有効化する必要があります。
この機能はWindows Pro系にしか導入されていないみたいで、その他の場合はVirtualBoxなどほかの仮想化技術の導入をする必要があります。

①Windowsボタン右の「ここに入力して検索」部分に"Windowsの機能の有効化または無効化"と入力

image.png

②検索文言の通りの設定画面が表示される
image.png

③その中からHyper-vという項目を探しチェックを付ける
image.png

以上でインストールの準備は完了

③の手順で、Hyper-vプラットフォームにチェックがつけられなかった場合

主に自作PCを使用している場合にチェックを付けられない可能性があって、調べてみるとBIOS画面から機能そのものを有効化しなければならないみたい。
もし同じ現象になった場合、「"マザボのメーカー名" BIOS Hyper-v」とかで検索すると、有効化の方法の記事が見つかるはず。
ちなみに僕はGIGABYTEのマザボなので以下の記事が参考になりました

「Hyper-Vをインストールできません」と表示された場合の対処方法

Docker Desktopのインストール

以下のリンクから環境にあったインストーラーをダウンロードしてください

Macを使用している場合のインストーラー
Windows10(pro)を使用している場合のインストーラー

ダウンロード後、手順に従って何も考えずインストールします。
何かしら選択する画面も出てくるが基本的になにもいじらなくてOK

インストールを完了時に再起動をすることになるため、ほかに開いているアプリなどがある場合は閉じておいてください

再起動後

Macならターミナル、Windowsならコマンドプロンプトなどで以下のコマンドを実行します。

docker -v

実行後、以下のバージョンが表示されればインストール完了です。

PS C:\Users\Kohei Takahashi> docker -v
Docker version 19.03.13, build 4484c46d9d

【Exception】再起動時にDocker Desktopからエラーメッセージが表示される場合

出たエラーが一概に僕と同一のものであるわけではないが、僕の場合「Linuxのカーネルないで」というエラーが出ました。
基本的にエラーメッセージと一緒にリンクが表示されている場合、そのリンク先に飛べば解決方法が丁寧に記載されているためその通りに進めてください。

Docker Composeをインストール

Dockerにはコンテナという概念があり、Docker Composeはそれらのコンテナを扱いやすくしてくれるツールです。
インストール方法は

[Docker] Windows 10 Pro 64bit に Docker と Docker Compose をインストールする
MacでDockerとdocker-composeをインストールする方法

上記の記事がわかりやすいです。

Dockerを使って実際に環境を構築していく

今回は前述のとおり、Laravel(PHP)+Apache+MySQLの環境を用意していきます!
もしチーム開発をする場合、ここからの作業は誰か一人が行って、他の人は「Dockerを立ち上げる」まで読み飛ばしてOKです。
フォルダ構成などに制限はないらしいけど、参考資料の通りの構成にました。
自分の好きなディレクトリに以下の構成でフォルダ・ファイルを作成しておいてください。

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

とっても綺麗。

続いて今用意した設定ファイルたちに命を吹き込んでいきます。

Dockerfile

まずは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

こちらも参考資料の丸パクリです。
このコマンド達が上から順に実行されていくようです。

000-default.conf

つづいてApacheの設定ファイルに命を吹き込みます。

<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>

ここに出てくる"laravelapp"というのは作成する予定のLaravelのアプリ名を入れてください。

php.ini

続いてphp.iniです

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

これは説明なしでもわかると思いますが、文字コードだったり「わいは日本人なんやから、日本に対応せいや」っていうことを定義してます。

my.cnf

設定ファイル最後はmy.cnfです

[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
[client]
default-character-set=utf8mb4

こちらは主に文字コードの設定です。

コンテナ楽々管理のDocker Compose

先ほどディレクトリ構成を書いた際、docker直下には"appディレクトリ"と"dbディレクトリ"がありましたが、それらはコンテナを分けるためにわかりやすく区別していました。
appコンテナとdbコンテナを作るわけですが、それらを楽に管理ができるDocker Composeというものがあります。
そのDocker Composeの設定ファイルが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:330

以上で設定ファイルたちは完了です。
Dockerを立ち上げてみましょう!

Dockerを立ち上げる

以下のコマンドを実行すると先ほど記述したdocker-compose.ymlの内容がコンテナとなります。

docker-compose build

その次は以下のコマンドでコンテナを起動しましょう

docker-compose up

これで起動されます。
ただ上記のコマンドで起動すると、バックグラウンドで実行されないためログが常に表示されます。
それは鬱陶しいので基本的には以下のコマンドを実行して起動します。

docker-compose up -d

これでバックグラウンドで実行されます。

ちなみに落としたい場合は

docker-compose down

これで落ちます。

Laravelプロジェクトを作成

次は実際にLaravelのプロジェクトをコンテナ内で作成しましょう!

以下のコマンドで先ほど作ったappコンテナのshellに入りこみます

docker exec -it laravel_app bash

入り込んだ先で以下の慣れ親しんだコマンドを入力してプロジェクトを作成します

composer create-project "laravel/laravel=~6.0" --prefer-dist laravelapp

上記の"laravelapp"と書かれている部分には開発したいプロジェクト名を入力してください。

実行した後はプロジェクトが作成されるまでしばらく待ちましょう!

Welcomeページを拝みに行く

先ほどdocker-compose.ymlで以下のような記述をしました

appコンテナの設定を抜粋
services:
 app:
   ports:
     - "8000:80" #ここ重要
   build: ./docker/app
   container_name: laravel_app
   volumes:
     - ./src:/var/www/html

appコンテナについての記述で"ports"というプロパティを設定していました、これはその名の通りポートで、dockerのコンテナを立ち上げると以下のURLで作成したlaravelプロジェクトを実際に見に行くことができます。

http://localhost:8000

これで確認できたら、ひとまずDocker上にlaravelのプロジェクトを作成することができています。

【Exception】なんか知らんけどPermission deniedされる場合

最初アクセスしたらこんなこと言われました

The stream or file "/var/www/html/dooga/storage/logs/laravel.log" could not be opened in append mode: failed to open stream: Permission denied

調べたところ、どうやらLaravelのlogファイルにapacheユーザーが書き込み権限を持たないため、logに書き込めずに例外が発生しているらしい。

chmod -R 777 /var/www/html/laravel_app/storage

上記のコマンドで解決することはできたが、なんか嫌です。と数時間探しまくっているとこんな記事発見
早速手順の通りやってみると見事表示された。
このユーザー権限がいいものなのかというと少し疑問ですが、まあ問題ない範囲であると思います。

【Exception】artisanコマンドできない場合

artisanコマンドを打つと以下のエラーがでてきました

Failed to clear cache. Make sure you have the appropriate permissions.

もしこれが出る場合は以下のフォルダ構成を確認してください。

├─app # 今回はおそらく関係ない
│  └─public
├─framework
│  ├─cache
│  │  └─data
│  ├─sessions
│  └─views
└─logs # 今回はおそらく関係ない

なにか手順が悪かったのか、そもそも作られないのか。理由は定かでありませんが、上記の"framework"というフォルダの中身が揃ってませんでした。てかそもそもframeworkっていうフォルダ自体なかった気がする。
おそらく書き込み権限がなかった関係で作れるもんも作ってくれなかったんじゃないかなと思います。
僕の環境ではこれらの解決で無事Welcomeページにたどり着きました。

DBの設定を行う

最後にDBの設定です。
それらの設定は.envというファイルにまとめられています。以下のように変更してください。

DB_CONNECTION=mysql
DB_HOST=laravel_db
DB_PORT=3306
DB_DATABASE=laravel_db  # docker-compose.ymlのMYSQL_DATABASE
DB_USERNAME=laravel_user  # docker-compose.ymlのMYSQL_DATABASE
DB_PASSWORD=laravel_pass  # docker-compose.ymlのMYSQL_PASSWORD

見覚えあるかと思いますが、これはdocker-compose.ymlにてdbコンテナの"environment"として設定した値です。起動時にDBも作成してくれているので、設定が済んだら実際にmigrateしてみましょう。

先ほどのようにappコンテナのshellに入り込みます。
リンクスタート!!ピュルルルルルーン!!(SAO風)

docker exec -it laravel_app bash

これで/var/www/htmlに入り込みました。
ここでlsを実行すると直下にlaravel_appがあることがわかります。

cd laravel_app # laravel_appに移動
php artisan migrate # migrate実行

上記コマンド実行後以下のようなログが表示されればマイグレーション成功です。一旦の環境構築完了と言えます。

Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (0.1 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (0.06 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (0.03 seconds)

今回は接続確認でのマイグレーションなので僕の場合この後はもとに戻します。

php artisan migrate:refresh

これでマイグレーション前の状態に戻ります。

【Exception】なんか知らんけどAccess deniedされる

上記ではスルッと終わってるように見えますがもちろんそんなことはなく、ここでも一瞬詰まりました。
理由はphp artisan migrate時にAccess deniedのエラーが表示されたためです。

エラーメッセージ
root@xxxxxxxxxxxx:/var/www/html/laravel_app# php artisan migrate # migrateの実行

   Illuminate\Database\QueryException  : SQLSTATE[HY000] [1045] Access denied for user 'laravel_user'@'172.21.0.3' 

なんで?と思って実際にmysqlの中身を見に行きました
その場合は一旦appコンテナから抜け出して

docker exec it laravel_db mysql -u root -p
Enter password:  # おそらくrootと入力でOK

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.31 MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

これでmysqlにrootユーザーでログインできました。
あとは存在しているユーザーを見に行きます。

mysql> select user from mysql.user;

すると僕の場合、laravel_dbのユーザーが作成されていませんでした。(もしかしたら当たり前なのかもw)

db:
   image: mysql:5.7
   container_name: laravel_db
   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
   volumes:
     - ./docker/db/data:/var/lib/mysql
     - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf
   ports:
     - 3306:330

だったらrootを常に使うユーザーとして.envファイルを変更してもいいのですが、せっかくならlaravel_userユーザーを使いたいですし、rootを通常時に使うのは宗教上の都合で死刑になってしまいます。

ではrootと同じ権限のlaravel_userを作ればいいんだ!(白目)

はい、じゃあroot使えよって感じですが、お付き合いください。

mysql> CREATE USER 'laravel_user'@'%' IDENTIFIED BY 'laravel_pass';

上記のCREATE分でlaravel_userが作成されます。
今度はrootと同じ権限を与えます。

mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'laravel_user'@'%' WITH GRANT OPTION;

このなっげぇ文でlaravel_userに権限を付与します。
本当にrootと同じ権限があるのかどうかを確認します。

mysql> select host,user,select_priv,create_priv,insert_priv,grant_priv,account_locked from mysql.user;
+-----------+---------------+-------------+-------------+-------------+------------+----------------+
| host      | user          | select_priv | create_priv | insert_priv | grant_priv | account_locked |
+-----------+---------------+-------------+-------------+-------------+------------+----------------+
| localhost | root          | Y           | Y           | Y           | Y          | N              |
| localhost | mysql.session | N           | N           | N           | N          | Y              |
| localhost | mysql.sys     | N           | N           | N           | N          | Y              |
| %         | root          | Y           | Y           | Y           | Y          | N              |
| %         | laravel_user  | Y           | Y           | Y           | Y          | N              |
+-----------+---------------+-------------+-------------+-------------+------------+----------------+
5 rows in set (0.00 sec)

これでこの呪縛から解放されました。

"まとめ"

以上でDockerでLaravel+Apache+MySQLの環境構築は完了です。
個人的に壁にぶち当たることが多すぎてなかなかスムーズにいけませんでしたが、とりあえず開発できる段階までいけたので満足です。
この環境をもう少し拡張していきたいなと考えていますので、その際はまた記事にします!
【関連記事】
DockerのLaravelにVue.jsも入れたらんかい!!

では

参考資料

非常にお世話になった参考資料です。
Laravelのパーミッションを適切に設定
Laravel 5.7 で php artisan cache:clear を叩くと Failed to clear cache. Make sure you have the appropriate permissions. になる。。
ERROR 1045 (28000): Access denied for userとなったときの対応方法
mysqlへログインできない問題

buzzdark1212
個人開発にてチームメンバーに初心者プログラマーがいるため、学んだことの共有として記事を投稿しています。 すでに誰かが書いている内容でも自分でアウトプットすることに意味を感じているため、内容被りはご了承お願いします。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away