DockerでMySQLサーバーを構築するときの環境変数の設定


DockerでMySQLサーバーを構築するためには、Dockerの公式が提供しているMySQLサーバー用のimageを使用することがほとんどだと思います。
公式のimageを利用してMySQL用のコンテナを構築する際は、やりたいことに応じて環境変数とMySQLのパラメータを設定する必要があります。
こちらの記事では、公式imageを利用する際の環境変数の設定ついてまとめています。

# 環境
Windows11
Dockerのバージョン 3.5.2
公式のDocker imageのバージョン mysql:8.0.32


# 最低限必要な環境変数

初めに最低限の設定でコンテナを起動してみます。
以下のComposeファイル(docker-compose.yml)を作成します。
公式のimageをそのまま利用しています。

```yml:docker-compose.yml
version: '3'
services:
  db:
    image: mysql:8
```
このComposeファイルを使用してコンテナを起動するとエラーで立ち上げに失敗します。
公式イメージではMySQLのrootユーザーでログインするためのパスワードを環境変数を用いて設定する必要があり、上記のComposeファイルでは設定が行われていないからです。

```:コンテナログ
db_1 | 2023-04-12 14:39:34+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
db_1 | You need to specify one of the following as an environment variable:
db_1 | - MYSQL_ROOT_PASSWORD
db_1 | - MYSQL_ALLOW_EMPTY_PASSWORD
db_1 | - MYSQL_RANDOM_ROOT_PASSWORD
```

ログにもあるとおり、以下の3つのうち最低1つの環境変数をコンテナ立ち上げのタイミングで設定していなければなりません。
- MYSQL_ROOT_PASSWORD=hoge
- MYSQL_ALLOW_EMPTY_PASSWORD="yes"
- MYSQL_RANDOM_ROOT_PASSWORD="yes"

**MYSQL_ROOT_PASSWORD**を設定すると、設定したパスワードでのログインが可能となります。
**MYSQL_ALLOW_EMPTY_PASSWORD**を設定すると、パスワードなしでのログインが可能となります。
**MYSQL_RANDOM_ROOT_PASSWORD**を設定すると、コンテナ起動時にランダム文字列でパスワードが設定されます。パスワードはログで出力されます。
```:MYSQL_RANDOM_ROOT_PASSWORD設定時のログ
'/var/lib/mysql/mysql.sock' -> '/var/run/mysqld/mysqld.sock'

2023-04-15 13:58:29+00:00 [Note] [Entrypoint]: GENERATED ROOT PASSWORD: DatpTV8+LUdWGcox6LrIWgEso5JYXczG
```

また、これら3つの環境変数を複数同時に設定した際の設定の優先順位は、以下のようになります(高い順)
1. **MYSQL_RANDOM_ROOT_PASSWORD**
2. **MYSQL_ROOT_PASSWORD**
3. **MYSQL_ALLOW_EMPTY_PASSWORD**


[Dockerfile](https://github.com/docker-library/mysql/blob/358c2e5ab6cd24b86a20a871820ecbc67a244368/8.0/Dockerfile.oracle)によると、初回起動時に/user/local/bin/docker-entrypoint.shを実行しており、その内部でバリエーションや設定を行っているようです。
詳しい処理が見たい場合はdocker-entrypoint.shを読んでみてください

# 環境変数の設定
今回は **MYSQL_ROOT_PASSWORD** を設定することを想定します。
```
MYSQL_ROOT_PASSWORD = p@ssw0rd
```

Dockerでは環境変数を複数の方法で設定することができます。
大きく分けるとComposeファイルで設定を行うか、コマンドで直接設定を行う方法です。

## Composeファイルで設定する場合

起動時の設定を記載するComposeファイル(docker-compose.yml)で環境変数を設定することができます。
docker-compose.ymlに記載して挙動の変化を確かめます。

### environmentオプションで設定

environmentオプションはコンテナに対して環境変数を設定することができます。

```yml:docker-compose.yml(environmentで環境変数を設定)
version: '3'
services:
  db:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: p@ssw0rd
```

このComposeファイルを使用してコンテナを起動します。
```bash:bash(local)
workspace> docker-compose up -d
Creating network "study_mysql_default" with the default driver
Creating study_mysql_db_1 ... done
```
コンテナにログインすると、rootユーザーでサーバーにログインします。
パスワードありでMySQLクライアントにログインをおこなうと無事接続が完了しました。

```bash:bash(container)
# ユーザーの確認
bash-4.4# id
uid=0(root) gid=0(root) groups=0(root)

# 環境変数の確認
bash-4.4# echo $MYSQL_ROOT_PASSWORD
p@ssw0rd

bash-4.4# mysql -uroot -p
Enter password: 【p@ssw0rdと入力】
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.32 MySQL Community Server - GPL

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

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

### env_fileオプションで設定

environmentオプションでは環境変数をComposeファイル上で直接指定していましたが、env_fileオプションはファイルを指定し、そのファイルに記載した環境変数を設定することができます。
試しに、db_enb_fileを作成して、そのファイル内に環境変数を記載します。

```:./env/db_env_file
MYSQL_ROOT_PASSWORD=p@ssw0rd
```
```yml:docker-compose.yml(env_fileで環境変数を設定)
version: '3'
services:
  db:
    image: mysql:8
    env_file: env/db_env_file
```

同様にMySQLクライアントにログインができることを確認できます。

```bash:bash(container)
# ユーザーの確認
bash-4.4# id
uid=0(root) gid=0(root) groups=0(root)

# 環境変数の確認
bash-4.4# echo $MYSQL_ROOT_PASSWORD
p@ssw0rd

bash-4.4# mysql -uroot -p
Enter password: 【p@ssw0rdと入力】
Welcome to the MySQL monitor.  Commands end with ; or \g.

// 省略

mysql> 
```

## `docker run`コマンドで設定する場合
`dokcer run`コマンドで設定する場合はオプションを利用します。
Composeファイルと同じようなオプションがあります。
設定後の挙動についてはComposeファイルを使用した場合と変わりません。

### `-e/--env`オプションで設定
`-e HOGE=fuga` の形で環境変数を設定することができます。
複数設定したい場合は`-e`オプションを複数記載します。
```bash
docker run --name study_mysql_db_1 -e MYSQL_ROOT_PASSWORD=p@ssw0rd -d mysql:8
```
### `--env-file`オプションで設定
環境変数を設定している外部ファイルを指定できます。
```bash
docker run --name study_mysql_db_1 --env-file env/db_env_file -d mysql:8
```

# 他に設定することができる環境変数
### MYSQL_DATABASE
コンテナ作成時に指定した名前のデータベースを作成します。
```:./env/db_env_file
MYSQL_ROOT_PASSWORD=p@ssw0rd
MYSQL_DATABASE=db_1
```

立ち上げたコンテナのデータベースを確認すると、設定した名前のデータベースが作成されていることが確認できます。
```
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| db_1               |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.01 sec)
```

### MYSQL_USER, MYSQL_PASSWORD
デフォルトではrootユーザーのみ作成されますが、これらの環境変数で任意のユーザーを追加で作成することができます。

```:./env/db_env_file
MYSQL_ROOT_PASSWORD=p@ssw0rd
MYSQL_USER=user_1
MYSQL_PASSWORD=p@ssw0rd2
```
これでuser_1ユーザーが追加で作成されます。
```
bash-4.4# mysql -uroot -p
Enter password: 【p@ssw0rdと入力】
Welcome to the MySQL monitor.  Commands end with ; or \g.
 // 以下省略

bash-4.4# mysql -uuser_1 -p
Enter password: 【p@ssw0rd2と入力】
Welcome to the MySQL monitor.  Commands end with ; or \g.
 // 以下省略
```

### MYSQL_ONETIME_PASSWORD
初回ログイン用のパスワードを設定します。
一度このパスワードでログインを行うとパスワード変更を強制するために、一度でパスワードを期限切れにする

```:./env/db_env_file
MYSQL_RANDOM_ROOT_PASSWORD="yes"
MYSQL_ONETIME_PASSWORD="true"
```
※自身の環境ではいくつかのパターンで試してみたのですが、うまく動作しませんでした。詳細については調査中です、

## 参考文献

- [Docker - mysql](https://hub.docker.com/_/mysql)
- [Docker で環境変数をホストからコンテナに渡す方法（ホスト OS 側からゲスト OS に渡す方法各種）](https://qiita.com/KEINOS/items/518610bc2fdf5999acf2#docker-compose-run-%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89)