【Dockerfile】ENV でタイムゾーンが設定された MySQL イメージをビルドする

# はじめに
この記事では、Dockerfile でタイムゾーンが設定された MySQL イメージをビルドする手順について記載します。
Dockerfile の `ENV` インストラクションへの理解促進の一環で行っています。

https://docs.docker.com/reference/dockerfile/#env

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

- Windows 11
- Docker Engine 26.1.1
- MySQL 8.4.0

# ベースイメージのタイムゾーンの確認
今回のベースイメージは、2024年6月時点で latest タグと同等の [`8.4.0`](https://github.com/docker-library/mysql/blob/319db566ac7fef45c22f3df15ee5e194a7c43259/8.4/Dockerfile.oracle) にします。

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

`8.4.0` の MySQL イメージからコンテナを起動し、現在時刻を確認します。
まずはコンテナを起動します。

```powershell
docker container run               `
--name db                          `
--rm                               `
--detach                           `
--env MYSQL_ROOT_PASSWORD=password `
--publish 3306:3306                `
mysql:8.4.0
```

:::note
コンテナ起動時のコマンド・オプションについては、[こちら](https://qiita.com/Yasushi-Mo/items/4539c0a1e17644788e26)の記事で解説しています。
:::

次に MySQL へ接続し、現在時刻を確認します。

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

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

コンテナでは、2024年6月23日1時3分であることがわかります。上記コマンド実行時の日本時間は、2024年6月23日10時3分なので、日本時間と9時間ずれています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/9a4993ed-718d-7206-e637-6f44ec9d3fa4.png)

続いて MySQL サーバーのタイムゾーン設定を確認します。

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

`system_time_zone` では、MySQL サーバー起動時のシステムタイムゾーンが UTC であることを示しています。
また、`time_zone` では、MySQL サーバーのタイムゾーンがシステムタイムゾーンと同じことを示しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/a6959dc4-73a2-9d33-ee87-0d649351334a.png)

システムタイムゾーンの設定は、環境変数 `TZ` で設定できます。そのため、次はコンテナの環境変数を確認します。

```powershell
docker container exec db printenv TZ
```

上記コマンドを実行しても何も出力されません。そのため、環境変数 `TZ` は設定されていないことがわかります。

ここまでの確認結果から以下のことがわかります。

- コンテナのシステムタイムゾーンが UTC
- システムタイムゾーンの設定を行う環境変数 TZ は未設定
- MySQL サーバーのタイムゾーンはシステムタイムゾーンと同じ

したがって、MySQL にタイムゾーンを設定するためには、環境変数 TZ の値を日本時間にする必要があります。

なお、ベースイメージのタイムゾーンの確認ができたので、db コンテナを停止します。

```powershell
docker container stop db
```

# イメージの環境変数を指定する `ENV`
イメージの環境変数の設定は、`ENV` インストラクションで行います。

https://docs.docker.com/reference/dockerfile/#env

環境変数 TZ の値を日本時間にするための値は、`Asisa/Tokyo` です。

```Dockerfile
FROM mysql:8.4.0

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

上記 Dockerfile からイメージをビルドします。

```powershell
docker image build --tag my-mysql:tokyo .
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/d8e6c1f0-2cc4-0899-dcc7-31295da6be88.png)

`my-mysql:tokyo` がビルドされたことを確認します。

```powershell
docker image ls my-mysql
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/a6a831ea-968e-1cd7-9d53-1b48c689cabe.png)

次はビルドしたイメージからコンテナを起動します。

```powershell
docker container run               `
--name db                          `
--rm                               `
--detach                           `
--env MYSQL_ROOT_PASSWORD=password `
--publish 3306:3306                `
my-mysql:tokyo
```

MySQL へ接続し、現在時刻を確認します。

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

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

コンテナの時間が日本時間と同じ、2024年6月23日10時56分であることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/3388e82f-b2e8-77c1-e404-7162e95d1b0c.png)


続いて MySQL サーバーのタイムゾーン設定を確認します。

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

システムタイムゾーンが `JST` になっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/f3035c9c-d20a-9242-57f8-c983d42e7f96.png)

次はコンテナの環境変数を確認します。

```
docker container exec db printenv TZ
```

今回は実行結果が出力され、`Asia/Tokyo` になっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/9d484413-bdaa-0653-4c7f-05fa6a006481.png)

# 参考
- [Dockerfile reference](https://docs.docker.com/reference/dockerfile/)
- [	鈴木亮「開発系エンジニアのためのDocker絵とき入門」秀和システム、2024](https://www.shuwasystem.co.jp/book/9784798071503.html)

# 関連記事

https://qiita.com/Yasushi-Mo/items/17f755b9160767947d3e

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