docker-composeでmysql接続エラー解決

2020年9月9日

docker-composeでphpとmysqlのチュートリアル的な研修内容をこなしていたら接続ができないエラーが起こって詰んでたので、そこから自力で脱出した備忘録残しときます。

エラーメッセージ

Error:SQLSTATE[HY000] [2002] Connection refused

ひとまず「docker mysql Connection refused」でググったらいい感じに手掛かりになるteratailのQ&A見つけました。
https://teratail.com/questions/116377

というかまったく同じ状況だったっぽくて、ようは接続先アドレスはlocalhostなんだけど、127.0.0.1ではなくてコンテナ用の仮想IPアドレスに接続してくれってことらしいです。

$dsn = 'mysql:host=127.0.0.1;dbname=mzn';  // これだとエラー
$user = 'user';
$password = 'pass';

try{
    $dbh = new PDO($dsn, $user, $password);

    print('接続に成功しました。<br>');

}catch (PDOException $e){
    print('Error:'.$e->getMessage());
    die();
}

phpのPDOクラスで設定してあげるhost名が間違っていると、「Connection refused」のエラーが吐かれてしまいます。

ポート番号とかパスワードなど、接続関係のもの全部同じエラーだそうなのでいろいろ遠回りしていました。(port=3366;とか追加してみたり ※無駄足)

正しいhost名を探す

アプリ内の mysql/docker-compose.yml ファイル内「services」でmysqlの設定が入っているプロパティ(サービス名)を探します。

今回は「db」でした。

services:
  db:
    image: mysql:5.6
    container_name: mzn_db
    restart: always
    env_file: ../.env_local
    ports:
      - "3366:3306"
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    volumes:
        - .:/docker-entrypoint-initdb.d/
        - ./mysql_files:/var/lib/mysql

docker-compose execコマンドを使います。

docker-compose exec db bash
# docker-compose exec [サービス名] [実行したい内容]

# コンテナbashに入れたら
cat /etc/hosts
172.18.0.2      [コンテナID]

見つけました。

今回の接続host名は「127.18.0.2」だったようです。

修正

さっそくdsnの中身を直します。

$dsn = 'mysql:host=127.18.0.2;dbname=mzn';

接続に成功しました。

きたー!

追記

今回のやり方でホストのIPアドレスはわかりますが、これは毎度動的に割り当てられるものらしく、この書き方では、次に起動させた時はまた検索してアドレスを手動で指定しなければなりません。

動的に割り振り、つまりDocker内で名前解決が行われているため、IPアドレスを探す必要はなく、dockerfile.ymlで定義されたサービス名を使用すればいいらしいです。

services:
  db:
    image: mysql:5.6
    container_name: mzn_db
    restart: always
    env_file: ../.env_local
  :

今回は「db」と名付けられているので次のようにするのが正解です。

$dsn = 'mysql:host=db;dbname=mzn';