【phpMyadmin x Docker】「PMA_USER」と「PMA_PASSWORD」とは何？必要なのか？

# 概要
`docker-compose.yaml`でphpmyadminを使っている方なら見たことあると思うのですが、`PMA_PASSWORD`をご存知でしょうか。

普段使ってなかったのですが、その存在を知ったので、今回これを使って実装しました。
「これってphpmyadmin用のもの？」「Mysqlサーバ側と違うユーザーとパスでもいいの？」という疑問があったので調べてみました。

# 前提

以下の簡易的な`docker-compose.yaml`を使用する前提です。


```yaml
version: '3.8'

services:
  mysql:
    image: mysql:latest
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: exampledb
    ports:
      - "3306:3306"
    volumes:
      - db_data:/var/lib/mysql

  phpmyadmin:
    image: phpmyadmin/phpmyadmin:latest
    restart: always
    environment:
      PMA_HOST: mysql
      PMA_USER: root
      PMA_PASSWORD: rootpassword
    ports:
      - "8080:80"
    depends_on:
      - mysql

volumes:
  db_data:
```

上記の状態で`docker-compose up`を行えば、phpMyadminへ正常にアクセスできます。
以下で登場する`PMA_PASSWORD`や`MYSQL_ROOT_PASSWORD`は上記のことを指します。

# `PMA_PASSWORD`はphpMyadmin専用のパスワード？
答えはNOです。
私は最初phpMyadmin用に新規にユーザーとパスワードを設定するための項目と思ったのですが、違いました。

上記の例で言えば、
・`PMA_USER`　-> `root`
・`PMA_PASSWORD` -> `MYSQL_ROOT_PASSWORD`で指定した`rootpassword`
とすることで、MySQLサーバーに接続することができます。

上記で`PMA_PASSWORD`を`MYSQL_ROOT_PASSWORD`と別のパスワードを設定すると以下の画面でエラーになります（ただし必ずしも一致しなくて良いケースがあるので後述）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/318b3892-22b2-1f39-9d99-49d872599b2c.png)

```
エラー
MySQL のメッセージ: 接続できません。設定が無効です。

 mysqli::real_connect(): (HY000/2002): Connection refused
 MySQL サーバに接続しようとしましたが拒否されました。config.inc.php のホスト、ユーザ名、パスワードが MySQL サーバの管理者から与えられた情報と一致するか確認してください。
 ```

同様に、この時点で`PMA_USER`を`root`以外にしても同じエラーでphpMyadminに入れません。
ちなみに 少し経ってから再試行すると以下のエラーに切り替わります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/5a919a20-ede4-da11-1b89-c853072cacea.png)

以下の部分のエラーメッセージが微妙に変わるようですが、ログイン画面すら出てこないのは同様です。
`mysqli::real_connect(): (HY000/1045): Access denied for user 'root'@'192.168.144.3' (using password: YES)`

# 絶対に`PMA_PASSWORD`と`MYSQL_ROOT_PASSWORD`は一致しなきゃだめ？

実はこれはNOです。
上述のケースは、まだデフォルト`root`ユーザー以外にユーザーがない場合。

`root`以外で定義したいんだ！って場合は、
以下の操作でまずALL権限のあるMySQLユーザーが作成できます。

```sh
$ docker exec -it mysql_container_name bash
$ mysql -uroot -prootpassword

$ CREATE USER 'foofoo'@'%' IDENTIFIED BY 'hogehoge';
$ GRANT ALL PRIVILEGES ON *.* TO 'foofoo'@'%';
$ FLUSH PRIVILEGES;
```

上記を実施すれば、以下のように定義してもルートユーザーとして使えます。
そしてこの場合は、`MYSQL_ROOT_PASSWORD`と一致していなくともOKです。

```yaml
    environment:
      PMA_HOST: mysql
      PMA_USER: foofoo
      PMA_PASSWORD: hogehoge
```

# 何のために`PMA_USER`と`PMA_PASSWORD`を定義するの？

ここまで来たら、次の質問はこれになると思います。

「`PMA_USER`と`PMA_PASSWORD`って不要なんじゃ？」

現状、わざわざ`docker-compose.yaml`で`PMA_USER`と`PMA_PASSWORD`を定義しなくとも、`mysql`の方で定義すればいいからです。新規ユーザを作成したとしても、わざわざ`PMA_USER`と`PMA_PASSWORD`で定義する意味はあるのでしょうか？

`PMA_USER`と`PMA_PASSWORD`の用途は、ズバリ「**ログイン画面（認証ページ）のスキップ**」です。
これらを定義していない場合は、毎回ログイン画面が出てきて、ユーザーとパスワードを入力する必要があります。

これらを定義することで、ブラウザからPHPMyAdminへのアクセス時に認証画面をスキップし、直接PHPMyAdminのインターフェースを表示するための暗号鍵のようなイメージとして使用されているのです。

ただし、誰でもログイン画面を通さずにデータベースにアクセスできる可能性がある、という状態はセキュリティリスク的にあまりよろしくないでしょう。常にユーザー認証を要求する方が安全と言えます。

# スキップができるワケは...`config.inc.php`にあった

上述のエラーメッセージにも記載のあった`config.inc.php`とは何なのか？
実は関係おおあり、というかこれを理解すると一番早かったです。

`config.inc.php`はphpMyAdminコンテナ内の特定の場所に配置されている設定ファイルのようなもので、データベース接続情報、認証情報、テーマ、セキュリティ設定などのカスタマイズができます。使用しているイメージによって違うかもしれませんが、私の場合は`/etc/phpmyadmin/`にありました。

[config 認証モード](https://docs.phpmyadmin.net/ja/latest/setup.html#auth-config)について、公式ドキュメントには以下のように説明がありました。

> クッキー認証や HTTP 認証とは異なり、最初に phpMyAdmin サイトを読み込んだときに、ユーザがログインする必要がありません。これは仕様によるものですが、インストール先へのアクセスをどのユーザにも許可しているということです。

つまり、config 認証モードを使用する場合は、`config.inc.php`ファイルに `PMA_USER` と `PMA_PASSWORD` を設定することで、直接的な認証情報を定義することができるのですが、`docker-compose.yaml`を利用して`PMA_PASSWORD`を定義してあげることもできる、ということです。この場合、環境変数として渡される認証情報は`config.inc.php`には直接書き込まれません。

確かに`config.inc.php`を見てみると以下のように記述があります。
これらの環境変数を受け取っているのですね。

```php
# cat config.inc.php 
<?php

require('/etc/phpmyadmin/config.secret.inc.php');

/* Ensure we got the environment */
$vars = array(
    'PMA_ARBITRARY',
    'PMA_HOST',
    'PMA_HOSTS',
    'PMA_VERBOSE',
    'PMA_VERBOSES',
    'PMA_PORT',
    'PMA_PORTS',
    'PMA_SOCKET',
    'PMA_SOCKETS',
    'PMA_USER',
    'PMA_PASSWORD',
    'PMA_ABSOLUTE_URI',
    'PMA_CONTROLHOST',
    'PMA_CONTROLPORT',
    'PMA_PMADB',
    'PMA_CONTROLUSER',
    'PMA_CONTROLPASS',
    'PMA_QUERYHISTORYDB',
    'PMA_QUERYHISTORYMAX',
    'MAX_EXECUTION_TIME',
    'MEMORY_LIMIT'
);
### 略
```

ということで、`PMA_USER`と`PMA_PASSWORD`について理解ができました。
ただし、セキュリティリスクもあると思うのでこれを利用する時はケースバイケースでご判断ください。