Laradockで簡単アプリ作成しようとしたら、速攻でDB周り/日本語問題で躓いたけど、チャチャッと解決


環境セットアップが完了した

ので、まずは、シンプルなCRUDなアプリを作って、お試しぃ〜、と思い、以下を参考に

作業を始めて、速攻で躓いた...

標準のユーザー認証を利用しようと、php artisan make:authして、DBへの反映でphp artisan migrateしたところ、以下のようなエラーで先に進めない

[Illuminate\Database\QueryException]                                                                     
SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_schema.tables where table_schema = laradock and table_name = migrations) 

[PDOException]                             
SQLSTATE[HY000] [2002] Connection refused

Laradockの初回起動後に、DB関連の設定を変更したことを思い出したので、--buildオプションをつけて再実行

docker-compose up --build -d nginx mysql

でも、同様のエラーが発生するので、DBが想定通りに作成されているかを確認

# docker-compose upして、mysqlのインスタンスに入る
docker-compose exec mysql bash

# mysqlの対象のDBに入れれば想定通り
mysql -u laradock -p laradock

mysql> show tables;
Empty set (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| laradock           |
+--------------------+
2 rows in set (0.01 sec)

mysql> exit
Bye

ということで、Laradock側は問題なさそう

色々検索していると、Dockerのサービス間は、サービス名でリンクしているとのこと

docker-compose.ymlの1行目でversion指定をしてますが、version2ですと、docker-compose.ymlに記述した全てのサービス間に自動的にリンクを張ってくれるようです(version1ではlinksを利用していた)。「ping サービス名」で自動的にリンクが貼られていることを確認できます。
Laravel : laradockでlaravelの開発環境構築 | DN-Web64

この辺り、まだ、Dockerの仕組みを把握していないのが問題...
原因はわかったので、Laravel側の以下の設定を変更して、無事解決

$LARAVEL_ROOT/.env
#DB_HOST=127.0.0.1
DB_HOST=mysql

以下のあたりも参照しました。

で、今度は、Seederで日本語をinsertした時に、文字化けが発生

mysql> select * from posts;
+----+--------+----------------+---------------------+---------------------+
| id | title  | body           | created_at          | updated_at          |
+----+--------+----------------+---------------------+---------------------+
|  1 | ?????  | ?????????????  | 2017-07-07 20:23:00 | 2017-07-07 20:23:00 |
|  2 | ?????? | ?????????????? | 2017-07-07 20:24:00 | 2017-07-07 20:24:00 |
+----+--------+----------------+---------------------+---------------------+
2 rows in set (0.00 sec)

以下のあたりで情報収集

まずは、MySQLに乗り込んでshow variables like '%char%';してみると、結果は、以下のようになっていた。

mysql> show variables like '%char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin1                     |
| character_set_connection | latin1                     |
| character_set_database   | latin1                     |
| character_set_filesystem | binary                     |
| character_set_results    | latin1                     |
| character_set_server     | latin1                     |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+

Laradock側の設定が足りないと思われるので、my.cnfの配置箇所を探して、設定変更

$LARADOCK_ROOT/mysql/my.cnf
[mysqld]
skip-character-set-client-handshake
character-set-server = utf8mb4
# collation-server = utf8mb4_general_ci
collation-server = utf8mb4_unicode_ci
init-connect = SET NAMES utf8mb4

[client]
default-character-set=utf8mb4

Laravel側については、どんな処理されているのか、念のためチェックしたところ、config/database.phpで以下のように記載があった。

config/database.php
'mysql' => [
    'driver' => 'mysql',
    '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' => '',
    'strict' => true,
    'engine' => null,
],

collationについては、どう検索でヒットさせたいのか、という要件によるので、それに合わせて適宜設定すべし。

で、Laradockに関しては、上述の設定をした後に、再度、--buildオプションをつけて、dockerを起動して見たところ、作成済みのDBはそのままだったので、対象DBのみ文字コードの変更は適用されず、以前のまま残っていた

mysql> show variables like '%char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8mb4                    |
| character_set_connection | utf8mb4                    |
| character_set_database   | latin1                     |
| character_set_filesystem | binary                     |
| character_set_results    | utf8mb4                    |
| character_set_server     | utf8mb4                    |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

既存DBの文字コードは、個別にALTRE文を流して、変更

mysql> ALTER DATABASE laradock CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Query OK, 1 row affected (0.01 sec)

mysql> show variables like '%char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8mb4                    |
| character_set_connection | utf8mb4                    |
| character_set_database   | utf8mb4                    |
| character_set_filesystem | binary                     |
| character_set_results    | utf8mb4                    |
| character_set_server     | utf8mb4                    |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.01 sec)

mysql> select * from posts;
+----+--------------------+--------------------------------------------+---------------------+---------------------+
| id | title              | body                                       | created_at          | updated_at          |
+----+--------------------+--------------------------------------------+---------------------+---------------------+
|  1 | 最初の記事         | 最初の記事のテキストです。                 | 2017-07-07 20:23:00 | 2017-07-07 20:23:00 |
|  2 | 二つ目の記事       | 二つ目の記事のテキストです。               | 2017-07-07 20:24:00 | 2017-07-07 20:24:00 |
+----+--------------------+--------------------------------------------+---------------------+---------------------+
2 rows in set (0.00 sec)

ということで、日本語を扱う場合は、いくつか、設定変更しないと正常に扱えないので、要注意!