【Docker・PHP】優先されるタイムゾーンの設定とは?

timezone システム開発

Docker + PHP で開発する場合、タイムゾーンを色々な場所に設定する事ができます。

php.ini
記述例

[Date]
date.timezone = "Europe/Madrid"

Dockerfile
記述例

FROM php:8.1.12-fpm

ENV TZ=America/Los_Angeles

docker-compose.yml
記述例

  php:
    container_name: php
    build: ./containers/php
    volumes:
      - ./src:/var/www/src:cached
    working_dir: /var/www/src
    environment:
      TZ: Asia/Tokyo

どこに定義されているかはプロジェクトによってまちまちだと思います。

ふと疑問に思ったのですが、全部に記述していた場合、一体どの設定が有効となるのだろう?
という事で実験してみました。

ちなみに、検証に使ったPHPのソースコードは、こんな感じです。

<?php

defaultTimezone = date_default_timezone_get();
var_dump(defaultTimezone );

1.php.ini, Dockerfile, docker-compose.yml の3箇所に定義

出力結果

string(13) "Europe/Madrid"

Dockerfile、 docker-compose.yml の設定を無視し、php.ini の設定が有効となりました。
どうやら php.ini の設定が最も優先されるようです。

続いて、php.ini の設定を削除して実験。

2.Dockerfile, docker-compose.yml の2箇所に定義

出力結果

string(3) "UTC"

あれ? どこにも定義していないはずの UTC が何故出てくる。

という事で、OSのタイムゾーンの設定を見てみる。

$ timedatect
bash: timedatect: command not found

$ echo $TZ
Asia/Tokyo

$ cat /etc/timezone
Etc/UTC

「Asia/Tokyo」と出てきたり「Etc/UTC」と出てきたりと、良く分からない状態に。

調べてみると、Dockerfileで環境変数 TZ を設定しただけでは、OSレベルのタイムゾーンが変更されるだけで、PHPの設定に反映されるわけでは無いらしい。
OSのタイムゾーンを PHPに反映させるには、tzone.ini に反映させる必要があるみたい。

という事で、Dockerfile を以下のように編集。

ENV TZ=Asia/Tokyo
RUN ln -snf /usr/share/zoneinfo/TZ /etc/localtime && echoTZ > /etc/timezone
RUN printf '[Date]\ndate.timezone="%s"\n', $TZ > /usr/local/etc/php/conf.d/tzone.ini

こうすると、上記のPHPコードの出力結果は、以下のように Dockerfile にて設定した内容が反映されます。

string(19) "America/Los_Angeles"

/etc/timezone も更新されます。

$ cat /etc/timezone
America/Los_Angeles

3.docker-compose.yml の1箇所に定義

出力結果

string(3) "UTC"

tzone.ini までアタッチ出来ていないので、予想通り。

念のため、OSのタイムゾーンの設定も確認。

$ timedatect
bash: timedatect: command not found

$ echo $TZ
Asia/Tokyo

$ cat /etc/timezone
Etc/UTC

「2」で書いたような事を docker-compose.yml に記述するのは不適かと思われますので、アプリのタイムゾーンを設定したい場合は、他で設定した方が良さそうです。
時々、タイムゾーンの設定を「TZ: UTC」と設定しているケースもありますが、実はデフォルトのタイムゾーン設定が生きているだけ、というケースもあるかもしれません。

ただ、php.ini を、こういう記述にしておけば、docker-compose.yml の設定を反映させてタイムゾーンを変更できます。

[Date]
date.timezone = ${TZ}

※php.ini をコンテナに配置する必要があります

こうすると、docker-compose.yml にて定義したタイムゾーンの設定が反映され、出力結果は以下のようになります。

string(10) "Asia/Tokyo"

まとめ

  • Dockerfile にて定義すると、OS のタイムゾーンは更新されても、PHPが参照するタイムゾーンは更新されない。tzone.ini への反映が必要。
  • そこまで書くのは面倒なので、タイムゾーン設定は、php.ini に記述した方がいい。
  • 可変にしたいなら、docker-compose.yml から変数を受け取って php.ini に反映させる

「あれ?このプロジェクト、どこでタイムゾーンの設定してるんだ?」
という状況に遭遇した場合、php.ini → docker-compose.yml → Dockerfile の順番で確認していくと良さそうです。

おまけ

date_default_timezone_set にてタイムゾーンを設定すると、上記の設定を上書きする。

<?php

date_default_timezone_set('Australia/Sydney');

defaultTimezone = date_default_timezone_get();
var_dump(defaultTimezone );

出力結果

string(16) "Australia/Sydney"

コメント

タイトルとURLをコピーしました