Fly.io 上で稼働している仮想マシンのTimezone設定を変更してみた

「[Fly.io の「Crontab with Supercronic」のページに従って定期処理の設定をやってみた](https://qiita.com/akase244/items/fdb3368b5f0aa0b77d26)」という記事を書いた際に、定期処理がUTCを基準に動作していることに気づいたので、JSTで動作するように仮想マシンのTimezone設定を変更してみました。

---

#### 仮想マシンの一覧を表示する

`fly machine list` コマンドで作成済みの仮想マシンの一覧を表示します。
今回、タイムゾーンの設定を確認したいのは定期処理用の仮想マシンなので、対象となるIDの値（今回の場合は「PROCESS GROUP」が「cron」のID）を控えておきます。

```
% fly machine list
2 machines have been retrieved from app アプリケーション名.
View them in the UI here (​https://fly.io/apps/[アプリケーション名]/machines/)

[アプリケーション名]
ID              NAME                STATE  	CHECKS  REGION	ROLE    IMAGE                                                   IP ADDRESS                      VOLUME CREATED       LAST UPDATED         PROCESS GROUP	SIZE                
XXXXXXXXXXXXXX  XXXX-XXXXXXXX-9999  started	        nrt   	        [アプリケーション名]:deployment-XXXXXXXXXXXXXXXXXXXXXXXXXX XXXX:9:XXXX:XXX:XXX:XXXX:XXXX:9 2024-08-10T11:34:56Z 2024-08-15T10:29:28Z cron          shared-cpu-1x:256MB	
ZZZZZZZZZZZZZZ  ZZZZ-ZZZZZZZZ-8888  started	        nrt   	        [アプリケーション名]:deployment-ZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZ:8:ZZZZ:ZZZ:ZZZ:ZZZZ:ZZZZ:8 2024-08-10T11:35:15Z 2024-08-15T10:45:55Z web           shared-cpu-1x:256MB			
```

---

#### 仮想マシンにログインする

`fly console` コマンドの引数 `--machine` に先ほど控えておいたIDを指定して、仮想マシンにログインします。

```
% fly console --machine XXXXXXXXXXXXXX
Connecting to XXXX:9:XXXX:XXX:XXX:XXXX:XXXX:9... complete
root@XXXXXXXXXXXXXX:/app# 
```

---

#### 変更前のタイムゾーンを確認する

一般的にタイムゾーンは `/etc/localtime` で制御されているので、このファイルの内容を確認します。
`/usr/share/zoneinfo/Etc/UTC` のシンボリックリンクになっているので、変更前はUTCであることが確認できました。

```
root@XXXXXXXXXXXXXX:/app# ls -l /etc/localtime 
lrwxrwxrwx 1 root root 27 Aug 12 00:00 /etc/localtime -> /usr/share/zoneinfo/Etc/UTC
```

環境変数 `TZ` には何もセットされていません。

```
root@XXXXXXXXXXXXXX:/app# echo $TZ

```

`date` コマンドを実行するとUTCと表示されることが確認できました。

```
root@XXXXXXXXXXXXXX:/app# date
Thu Aug 15 11:16:08 UTC 2024
```

---

#### タイムゾーンを変更する（環境変数 `TZ` を利用する方法）

Fly.ioのデプロイで利用しているDockerfileに以下の記述を追加し、環境変数 `TZ` に `Asia/Tokyo` を設定します。

```
ENV TZ="Asia/Tokyo"
```

または

Fly.ioのデプロイで利用しているfly.tomlに以下の記述を追加し、環境変数 `TZ` に `Asia/Tokyo` を設定します。

```
[env]
  TZ = 'Asia/Tokyo'
```

デプロイを実行します。

```
% fly deploy
```

---

#### 変更後のタイムゾーンを確認する

`/etc/localtime` は変更前と変わらず、 `/usr/share/zoneinfo/Etc/UTC` のシンボリックリンクになっていることが確認できました。

```
root@XXXXXXXXXXXXXX:/app# ls -l /etc/localtime 
lrwxrwxrwx 1 root root 27 Aug 12 09:00 /etc/localtime -> /usr/share/zoneinfo/Etc/UTC
```

環境変数 `TZ` に `Asia/Tokyo` がセットされています。

```
root@XXXXXXXXXXXXXX:/app# echo $TZ
Asia/Tokyo
```

`date` コマンドを実行するとJSTと表示されることが確認できました。
環境変数 `TZ` の値は `/etc/localtime` よりも優先されるので、この状態であれば定期処理がJSTを基準に実行されます。

```
root@XXXXXXXXXXXXXX:/app# date
Thu Aug 15 20:26:45 JST 2024
```

---

#### タイムゾーンを変更する（ `/etc/localtime` を利用する方法）

環境変数 `TZ` を利用せず `/etc/localtime` のシンボリックリンクをUTCからJSTに変更することも可能です。
その場合はDockerfile内に以下の記述を追記します。

```
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
```

上記の修正を行うと、以下のように `/etc/localtime` のシンボリックリンクが変更され、 `date` コマンドがJSTで表示されるようになります。

```
root@XXXXXXXXXXXXXX:/app# ls -l /etc/localtime 
lrwxrwxrwx 1 root root 30 Aug 15 20:48 /etc/localtime -> /usr/share/zoneinfo/Asia/Tokyo

root@XXXXXXXXXXXXXX:/app# date
Thu Aug 15 20:50:44 JST 2024
```

---

#### 定期処理がJSTで動作していることを確認する

Live Logsの画面を表示すると、定期処理の実行時間に「+09:00」という表記が確認できるので、JSTで動作していることがわかります。

![スクリーンショット_2024-08-15_21_30_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23093/c18e1d67-e153-2fd5-4f4b-172a25a5146c.png)

---

- 参考URL
    - [Linuxのタイムゾーンまわり CentOS7編](https://qiita.com/szly/items/dcc67c85689725795c26)
    - [タイムゾーンの設定](https://zenn.dev/hi_ka_ru/articles/53b6c5da6f38fc)
    - [Linuxの時刻管理](https://envader.plus/course/12/scenario/1118)
    - [fly.ioのタイムゾーンを変更](https://taroooth.hatenablog.com/entry/2023/08/20/090110)
    - [App is using wrong timesone](https://community.fly.io/t/app-is-using-wrong-timesone/11517/1)