こちらの記事で触れたリマインダーの時間がずれる件ですが、 GitHub に Issue #608 を立てたところ、コンテナのタイムゾーンに関するコメントがつきました。
また、似たようなタイムゾーン絡みと思われる Issue #566 でも、コンテナのタイムゾーンを確認するようにあコメントがありました。
これらからすると、どうも、OS(コンテナ)のタイムゾーンが影響しているっぽいようです。というわけで、なんとかならないかいろいろと試してみたので、そのときの顛末をメモっておきます。
なお、動作環境は以下の通りです。
- QNAP TS-262
- QTS 5.2.3.3006
- Container Station 3.0.9.1038 (2024/11/08)
- Pleasanter 1.4.13.0 (docker 版)
コンテナのタイムゾーンを変更してみる
冒頭に書いたように、どうも、時間周りの処理はコンテナ側のタイムゾーン設定も絡んでいるようです。コンテナのタイムゾーンはデフォルトだと UTC になります。ということで、まずは、下記を参考にして、コンテナのタイムゾーンを JST (Japan Standard Time, 日本標準時)に設定します。
Dockerコンテナのタイムゾーン変更方法 #Docker - Qiita
具体的には、 docker-compose.yml で
services: db: container_name: postgres image: postgres:16 environment: - POSTGRES_USER - POSTGRES_PASSWORD - POSTGRES_DB - POSTGRES_HOST_AUTH_METHOD - POSTGRES_INITDB_ARGS - TZ=Asia/Tokyo volumes: - type: volume source: pg_data target: /var/lib/postgresql/data pleasanter: container_name: pleasanter image: implem/pleasanter:1.4.13.0 depends_on: - db ports: - '50001:8080' environment: Implem.Pleasanter_Rds_PostgreSQL_SaConnectionString: ${Implem_Pleasanter_Rds_PostgreSQL_SaConnectionString} Implem.Pleasanter_Rds_PostgreSQL_OwnerConnectionString: ${Implem_Pleasanter_Rds_PostgreSQL_OwnerConnectionString} Implem.Pleasanter_Rds_PostgreSQL_UserConnectionString: ${Implem_Pleasanter_Rds_PostgreSQL_UserConnectionString} TZ: Asia/Tokyo volumes: - type: bind source: ./Mail.json target: /app/App_Data/Parameters/Mail.json - type: bind source: ./BackgroundService.json target: /app/App_Data/Parameters/BackgroundService.json - type: bind source: ./Service.json target: /app/App_Data/Parameters/Service.json volumes: pg_data: name: ${COMPOSE_PROJECT_NAME:-default}_pg_data_volume
のようにしてコンテナに対して、環境変数 TZ でタイムゾーンを指定するようにしました。
この docker-compose.yml を使って、こちらの記事の手順でコンテナを起動します。
実際にコンテナに入って、タイムゾーンを確認してみると、
pleasanter のコンテナでは
[user1@nas01 pleasanter-tmp]$ docker exec -it pleasanter2 /bin/bash root@582f1c28348d:/app# date Mon Mar 31 18:31:06 JST 2025 root@582f1c28348d:/app#
タイムゾーンが JST になってますね。もう一つの postgres のほうも
[user1@nas01 pleasanter-tmp]$ docker exec -it postgres2 /bin/bash root@74f21960a562:/# date Mon Mar 31 06:31:32 PM JST 2025 root@74f21960a562:/#
タイムゾーンが変わってますね。 Postgres 自身の設定を確認すると、
root@74f21960a562:/# psql -U Implem.Pleasanter_Owner Implem.Pleasanter psql (16.8 (Debian 16.8-1.pgdg120+1)) Type "help" for help. Implem.Pleasanter=> show timezone; TimeZone ------------ Asia/Tokyo (1 row) Implem.Pleasanter=>
こちらも問題なくタイムゾーン設定が反映されてますね。
テスト
さて、コンテナのタイムゾーンを変更したので、これで一度テストしてみます。『入門プリザンター』の『7.4 リマインダーを設定する』に従って、リマインダーを設定します。
これで、リマインダーが正しく送られるはずです。指定した時刻になると、正しくリマインダーが動いたようで、ちゃんとメールがやってきました。
と喜んだのもの束の間、なぜか下記のように大量のメールがやってきていました。
これ、リマインダーに該当するレコードって、1件しかないんですよ(というより、レコードそのものもテスト用の1件だけ)。
あきらかに挙動がおかしいですね。取り急ぎ、リマインダーの設定を『無効』にして、
あふれそうなメールを削除しておきます。あーあ。
試行錯誤とその結果
ここから、何が問題なのかいろいろと探りましたが、なかなか正しい挙動になりません。結局、1日ぐらい費やしてやっと見つけたのは、 Service.json の TimeZoneDefault の設定を変更してやる。というものでした。
つまり、最終的に Service.json を
{ "Name": "Implem.Pleasanter", "TimeZoneDefault": "Asia/Tokyo", "DefaultPassword": "pleasanter", "DeploymentEnvironment": null, "WithoutChangeDefaultPassword": false, "DefaultLanguage": "ja", "AbsoluteUri": "http://nas01:50001", "MaxRequestBodySize": 30000000, "RequireHttps": false, "AnnouncementSiteId": 0, "ShowProfiles": true, "ShowChangePassword": false, "ShowStartGuide": true, "Demo": false, "DemoUsagePeriod": 60 }
のようにして、 TImeZoneDefault に Asia/Tokyo を設定しておけば、リマインダーが動作した際に、設定した JST の時刻に、1件のレコードにつき1つメールが送られるようになりました。
結論
ということで、すくなとも手元の docker 環境では、
- CodeDefiner の /z 指定: Asia/Tokyo
- コンテナのタイムゾーン設定:JST (TZ環境編素で指定)
- Service.json の TimeZoneDefault 設定:Asia/Tokyo
の3つをそろえてやらないと、リマインダーとして期待した動作をしてくれませんでした。ご参考までに。
(おまけ)タイムゾーン設定がうまくいかなかった原因について
元々 Docker で動作させる際の手順の際に CodeDefiner を呼び出していますが、この時、 タイムゾーンを引数で指定しています。
docker-compose.codedefiner.yml
services: codedefiner: container_name: codedefiner image: implem/pleasanter:codedefiner depends_on: - db command: "_rds /y /l \"ja\" /z \"Asia/Tokyo\"" environment: Implem.Pleasanter_Rds_PostgreSQL_SaConnectionString: ${Implem_Pleasanter_Rds_PostgreSQL_SaConnectionString} Implem.Pleasanter_Rds_PostgreSQL_OwnerConnectionString: ${Implem_Pleasanter_Rds_PostgreSQL_OwnerConnectionString} Implem.Pleasanter_Rds_PostgreSQL_UserConnectionString: ${Implem_Pleasanter_Rds_PostgreSQL_UserConnectionString}
また、下記の公式ドキュメントの書きっぷりからして、 Service.json の TimeZoneDefault の設定は無視される( CodeDefiner の引数の設定が優先される)のだろうと思っていました。
が、どうも、少なくとも手元の環境では、 Service.json も変更しないと正しく動作しなかったようです。
このへん、どういう事情なんだろうか?と思って、もう少し調べると、いい記事がありました。
これによると、 CodeDefiner でタイムゾーンと言語を指定した場合、 Service.json 内の記述を『書き換える』ようです。確認してみます。
docker-compose.codedefiner.yml をこちらの記事で書いたものから、下記のように変更します。
services: codedefiner: container_name: codedefiner2 image: implem/pleasanter:codedefiner depends_on: - db command: "_rds /y /l \"ja\" /z \"Asia/Tokyo\"" environment: Implem.Pleasanter_Rds_PostgreSQL_SaConnectionString: ${Implem_Pleasanter_Rds_PostgreSQL_SaConnectionString} Implem.Pleasanter_Rds_PostgreSQL_OwnerConnectionString: ${Implem_Pleasanter_Rds_PostgreSQL_OwnerConnectionString} Implem.Pleasanter_Rds_PostgreSQL_UserConnectionString: ${Implem_Pleasanter_Rds_PostgreSQL_UserConnectionString} volumes: - type: bind source: ./Mail.json target: /app/Implem.Pleasanter/App_Data/Parameters/Mail.json - type: bind source: ./BackgroundService.json target: /app/Implem.Pleasanter/App_Data/Parameters/BackgroundService.json - type: bind source: ./Service.json target: /app/Implem.Pleasanter/App_Data/Parameters/Service.json
変更点は、バインドマウントを使って、ホスト側の Service.json を使うようにしました。
これを用いて、 codedefienr を実行して、
[user1@nas01 pleasanter-tmp2]$ docker compose -f docker-compose.yml -f docker-compose.codedefiner.yml run --rm codedefiner [+] Creating 1/0 ✔ Container postgres3 Running 0.0s <INFO> Starter.Main: Implem.CodeDefiner 1.4.13.0 <INFO> RdsConfigurator.UpdateDatabase: Implem.Pleasanter <INFO> UsersConfigurator.Execute: Implem.Pleasanter_Owner <INFO> UsersConfigurator.Execute: Implem.Pleasanter_User <INFO> SchemaConfigurator.Configure: Implem.Pleasanter <INFO> Configurator.OutputLicenseInfo: ServerName: db Database: pleasanterdb Deadline: 01/01/0001 Licensee: Users: 0 <INFO> Configurator.OutputLicenseInfo: This edition is "Community Edition". (略) <INFO> PrivilegeConfigurator.Execute: Implem.Pleasanter_User <SUCCESS> Starter.ConfigureDatabase: Database configuration has been completed. <SUCCESS> Starter.Main: All of the processes have been completed. [user1@nas01 pleasanter-tmp2]$
ホスト側の Service.json を表示させてみると、
[user1@nas01 pleasanter-tmp2]$ cat Service.json { "Name": "Implem.Pleasanter", "TimeZoneDefault": "Asia/Tokyo", "DefaultPassword": "pleasanter", "DeploymentEnvironment": null, "WithoutChangeDefaultPassword": false, "DefaultLanguage": "ja", "AbsoluteUri": "http://nas01:50001", "MaxRequestBodySize": 30000000, "RequireHttps": false, "AnnouncementSiteId": 0, "ShowProfiles": true, "ShowChangePassword": false, "ShowStartGuide": true, "Demo": false, "DemoUsagePeriod": 60 }[user1@nas01 pleasanter-tmp2]$
TimeZoneDefault と DefaultLanguage が書き換わってますね。その意味では、公式ドキュメントの表記は、 CodeDefiner の引数を優先するという意味ではなく、文字通り『書き換える』ということを指しているのですね。
でも、今回使っているのは、 docker 版です(おまけにバインドマウントも使っていません)。なので、仮に CodeDefiner の実行により Service.json を書き換えても、 上にあげた記事中で指摘されているように Postgres の Users テーブルのデフォルト値には反映されても、 pleasanter コンテナ内の Service.json ファイルの内容には影響を及ぼしません。
なるほどね。だから、 pleasanter コンテナ側の Service.json を書き換えておかないと、デフォルトのタイムゾーンが UTC となり、正しく動作してくれなかったということになるようです。納得、納得。
もっとも、メールが山ほど飛んできた部分は相変わらずなぞですが、これもタイムゾーン設定が一貫していないことが何かの要因なのでしょう、きっと。
(おまけ)その2
上記の推測が正しいならば、 Docker でパラメータファイルを変更する場合の手順
の場合も、各パラメータファイルを DockerFile 内で COPY しているので、 CodeDefiner の引数で指定したタイムゾーンが pleasanter コンテナ側に反映されないのは同じように思えます。ということで、これも似たような現象が起きるように思えますね。こちらは試してないのですが、どなたか知ってますかね?
ま、なんにせよ、 Pleasanter の Docker 版を使う際は、タイムゾーンの取り扱いにはちょっと注意したほうがいいかも、ということでした。