DockerでLaravelの環境構築をした際につまづいたので手順をまとめました。

久し振りの更新です。
この一年間、福岡市内の某Web制作会社に入社して仕事をしていました。
業務内容はフロントエンドエンジニア、プロジェクトマネージャーの他、システム開発を行なっているグループ会社の新人研修の講師や障害者支援施設の施設外就労指導員なども担当させていただいておりました。
とてもエキサイティングな環境でたくさん刺激をいただいたものの、多発性硬化症という難病を患い休養のために今年10月末で退社することになりました。
しばらくは家でゆっくりしつつ、今までやりたかった勉強や趣味に打ち込もうかなというところです。

かねてよりバックエンド側のことも覚えたいなと常々考えていたので、以前購入していたLaravel入門の本を読みながらLaravelの勉強を始めました。(今は第二版が出ていますが、私が買った当時に出ていたのは初版だったのでそれを使っています。)

・・・なんですが、そのままストレートに本の手順を踏んで勉強すれば良いのに、「やっぱりローカル環境はDockerで構築したいよなぁ」なんて思ってしまったので、ちょっと色々沼にはまりました。。。

最初はQiitaのこちらの記事をそのまま参照してやってみました。:「dockerでLaravel環境構築
それで、Laravelの初期画面が表示されるところまではうまく行きました。が。

最初の沼:下層ディレクトリが404になる

localhost/hello のようなURLにアクセスしようとすると404になります。。。
ルーティングの記述はおかしくないのに。
で、調べたらどうもnginXの設定を変える必要があったみたいです。

default.confのnginXの設定を以下のように変更します。
nginx/default.conf
server {
  listen 80;
    index index.php index.html;
    root /var/www/public;

  location / {
    try_files $uri $uri/ /index.php?$query_string;
    }

  location ~ \.php$ {

  try_files $uri =404;
  fastcgi_split_path_info ^(.+\.php)(/.+)$;
  fastcgi_pass php:9000;
  fastcgi_index index.php;
  include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
  }
 }

よしよし、これで上手くいった。
このままデータベースを作成してどんどん進めていきましょ。
・・・しかし、例のLaravel入門ではmySQLではなくSQLiteを使って解説しているんですよね。
しかも、ターミナルからコマンドを入力する際も、dockerを使ってるからちょっと勝手が違う。

第2の沼:DBのテーブル作成の仕方がよくわからない

まずは、DB自体はdocker-compose up -dを実行したら作成されるわけですよ。
ただ、そこから先、ターミナルからどうやってテーブルを作成したら良いの??という状態になりました。
結論をいうと、ターミナルで以下を実行してコンテナ内に入ります。

docker exec -t db-host bash

このdb-hostという部分にDBのコンテナ名を入れるんだなという情報に行き着くまでに時間がかかりました。
ちゃんとdockerの知識がないと無理だなと思ったので、ちゃんと買って読みましたよ、dockerの技術書。「さわって学ぶクラウドインフラ docker基礎からのコンテナ構築」という本なんですが、これわかりやすかったです。
これで無事にコンテナ内に入ることができたので、mySQLコマンドを-pオプション付き(パスワードを入力するため)で実行します。

root@3ff836f81892:/# mysql -p

次に、データベースを使用するためのコマンドを入力します。(ここではdatabaseという名前のデータベースを使用)

mysql> USE database;

すると「Database changed」と表示されるので、mySQLコマンドでテーブルを作成します。
しかし、Laravel入門の記述そのままだと、SQLiteでの入力方法になっているから上手くいかない。
なので、以下のように実行してテーブルを作成(ここではpeopleという名前のテーブル)。

mysql> CREATE TABLE people (
    -> id INTEGER AUTOINCREMENT,
    -> name TEXT NOT NULL,
    -> mail TEXT,
    -> age INTEGER,
    -> PRIMARY KEY(id)
    -> );

ここまで上手くいったらテーブルにレコードを追加。

mysql> INSERT INTO people VALUES (1, 'taro', 'taro@yamada.jp', 35);
mysql> INSERT INTO people VALUES (2, 'hanako', 'hanako@flower.com', 24);
mysql> INSERT INTO people VALUES (3, 'sachiko', 'sachi@happy.org', 47);
mySQLを終了します。
mysql> exit

ようやくDBの準備ができたので、LaravelからDBを利用するためにコードを書き換えます。

config/database.php
mySQLを使う場合:
'default' => env('DB_CONNECTION', 'mysql'),
<mySQLの設定は以下の部分を編集>
'mysql' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],
使用するデータベース名を指定。(ここでは’database’という名前のデータベース)
'database' => env('DB_DATABASE', 'database'),
データベースにアクセスする際に使用するユーザー名とパスワード(docker-compose.ymlで指定したユーザー名とパスワード)
'username' => env('DB_USERNAME', 'docker'),
'password' => env('DB_PASSWORD', 'docker'),

第3の沼:環境変数の指定でつまづく

さーてようやくいい感じになりました。あとは環境変数の指定を変更します。
本に書いてある通り、.envというファイルを編集すれば良いんですね。やってみましょう。
初期値は以下の通りです。

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=

これを以下のように編集します。

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=database
DB_USERNAME=docker
DB_PASSWORD=docker

よし!それではindex.blade.phpファイルを編集してDBの中身を表示させてみよう!

・・・あれ!?

エラーが表示される!?

なにこれ。どうもデータベースの接続が上手くいってないみたい。。。

本の通りにやっても上手くいかないということは、やはりdockerを使っているあたりに原因がありそう。
ということでgoogle先生に「docker laravel db connection refused」といった感じでお尋ねしました。
色々な記事を見ましたが、どうもやはり環境変数のあたりが怪しそう。
再び.envファイルを眺めます。DB_HOSTの部分でDBのコンテナ名を指定してあげないといけないみたい。

なので、以下のように変更します。

DB_HOST=db-host

この状態でdocker-compose downしてもう一度docker-compose up -dをやってみたら・・・

ようやく上手くいきました。ここまで長かった。。。

 

<追記>
ただし、このままだとデータベースにレコードを追加する際、NOT NULLであるフィールドにNULLをInsertしようとするとエラーになるので、以下の設定変更によりこの警告を無効化することで対処。
config/database.php
'strict' => false,

この手順はEvernoteにもまとめています。良かったらどうぞ。