【Docker Compose】Dockerfile から MySQL コンテナを作成する

# はじめに
この記事では、Docker Compose を使って Dockerfile から MySQL コンテナを作成する手順について記載します。

# 開発環境
開発環境は以下の通りです。

- Windows11
- Docker Engine 27.0.3
- Docker Compose 2
- MySQL 9.0.0

# Dockerfile の作成
今回は以下の要件を満たす Dockerfile を作成します。

- タイムゾーンが日本
- クエリログが出力される

最初にベースイメージを選択します。今回は、2024年7月時点で latest タグと同等の [`9.0.0`](https://github.com/docker-library/mysql/blob/3d11822710789e82f64f08c578162a5b804d2f2f/innovation/Dockerfile.oracle) にします。

https://hub.docker.com/_/mysql

```Dockerfile
FROM mysql:9.0.0
```

次にタイムゾーンを日本に設定するインストラクションを追加します。

```Dockerfile
# ENV <key>=<value> ...
ENV TZ=Asia/Tokyo
```

最後にログの出力設定をします。
まずはホストマシンで MySQL サーバー設定ファイルを作成します。

```my.cnf
[mysqld]
general_log = 1
general_log_file = /var/log/query.log
```

- [`general_log`](https://dev.mysql.com/doc/refman/9.0/en/server-system-variables.html#sysvar_general_log) : 一般クエリログの有効化
- [`general_log_file`](https://dev.mysql.com/doc/refman/9.0/en/server-system-variables.html#sysvar_general_log_file) : 一般クエリログの出力先ファイル名

作成したファイルをコンテナにコピーするインストラクションを追加します。

```Dockerfile
# COPY [OPTIONS] <src> ... <dest>
COPY ./my.cnf /etc/my.cnf
```

Dockerfile が完成しました。

```Dockerfile
FROM mysql:9.0.0

# ENV <key>=<value> ...
ENV TZ=Asia/Tokyo

# COPY [OPTIONS] <src> ... <dest>
COPY ./my.cnf /etc/my.cnf
```

# compose.yaml の作成
compose.yaml を作成します。

```compose.yaml
services:
  db:
    build: .
    container_name: "db-container"
    environment:
      - MYSQL_ROOT_PASSWORD=password
    ports:
      - "3306:3306"
```

- `build` : Dockerfile ファイルのパス（Dockerfile からイメージをビルド）
- `container_name` : コンテナ名を明示的に指定
- `environment` : MySQL のルートパスワード
- `ports` : 公開するポート

# 動作確認
準備ができたので、動作確認をします。

## コンテナの起動確認
まずはイメージをビルドして、コンテナを起動します。

```powershell
docker compose up --build --detach
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/fe55e905-070c-b39d-54dd-dc54a40f131d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/a81709f5-4999-9395-827d-523d628c758e.png)

コンテナの起動状況を確認します。

```powershell
docker container ls
```

コンテナ名 `db-container` が起動しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/dc0d27cf-6387-7ec9-4b80-5ad8a9eb408b.png)

## タイムゾーンの確認
次は MySQL に接続してタイムゾーンを確認します。
MySQL に接続します。

```powershell
mysql --host=127.0.0.1 --port=3306 --user=root --password=password
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/5dfa9cde-f166-0504-38f2-33fedc6a1aa1.png)

現在時刻を確認します。

```mysql
select now();
```

日本の時刻になっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/6d73d136-959f-b5de-843d-0c4b7e47aaad.png)

タイムゾーンの設定を確認します。

```mysql
show variables like '%time_zone%';
```

JST になっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/39d0a0b3-e7f9-93c9-60f8-0994851928a0.png)

## ログの確認
MySQL サーバー設定ファイル（`my.cnf`）で設定した `query.log` ファイルの存在を確認します。

```powershell
docker container exec db-container ls /var/log
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/28852bc2-1d27-4c62-8819-973ac21c6a04.png)

`query.log` ファイルの末尾5行を確認します。

```powershell
docker container exec db-container tail -n 5 /var/log/query.log
```

タイムゾーンの確認時に実行したクエリが表示されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/6fcec2d4-052b-fd5e-55e9-acad1d256e3a.png)


# 参考
- [Dockerfile reference](https://docs.docker.com/reference/dockerfile/)
- [7.1.8 Server System Variables](https://dev.mysql.com/doc/refman/9.0/en/server-system-variables.html)

# 関連
https://github.com/yasushi-mo/docker-samples/tree/main/mysql

https://qiita.com/Yasushi-Mo/items/fe9edaaa1e368bd593a7

https://qiita.com/Yasushi-Mo/items/74d96f6f60b27a121bc0

https://qiita.com/Yasushi-Mo/items/d2e920112adc6e31e4e2