DEV Community

kakisoft
kakisoft

Posted on

Docker/PHP - What is the most prioritized timezone setting?

When you use Docker & PHP, you can set timezone to many places.

php.ini
example

[Date]
date.timezone = "Europe/Madrid"
Enter fullscreen mode Exit fullscreen mode

Dockerfile
example

FROM php:8.1.12-fpm

ENV TZ=America/Los_Angeles
Enter fullscreen mode Exit fullscreen mode

docker-compose.yml
example

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

It depends on project where the value is set.

I wondered what is the most prioritized timezone setting if I set all of places differently.

Here is a source code that I used to research.

<?php

$defaultTimezone = date_default_timezone_get();
var_dump( $defaultTimezone );
Enter fullscreen mode Exit fullscreen mode

1. define 3 places, php.ini, Dockerfile and docker-compose.yml

Result.

string(13) "Europe/Madrid"
Enter fullscreen mode Exit fullscreen mode

Dockerfile and docker-compose.yml definitions were ignored and php.ini definition was reflected.
It seems like php.ini definition is the most prioritized.

Next, remove php.ini definition and execute.

2. define 2 places Dockerfile and docker-compose.yml

Result.

string(3) "UTC"
Enter fullscreen mode Exit fullscreen mode

Why? UTC appeared which is not defined anywhere.

So, I checked OS timezone setting.

$ timedatect
bash: timedatect: command not found

$ echo $TZ
Asia/Tokyo

$ cat /etc/timezone
Etc/UTC
Enter fullscreen mode Exit fullscreen mode

Each command showed different result such as "Asia/Tokyo" and "Etc/UTC". It is a bit confusing.

After researching I found out that timezone setting will not be reflected to PHP setting only by defining environment valuable "TZ" in Dockerfile.
If you want to use OS timezone, you have to define in tzone.ini.

So, I edited Dockerfile.

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

Then, the result of PHP code execution, timezone setting in Dockerfile is reflected.

string(19) "America/Los_Angeles"
Enter fullscreen mode Exit fullscreen mode

/etc/timezone will be updated.

$ cat /etc/timezone
America/Los_Angeles
Enter fullscreen mode Exit fullscreen mode

3. define 1 places docker-compose.yml

Result.

string(3) "UTC"
Enter fullscreen mode Exit fullscreen mode

The result is same as I expected because tzone.ini is not set.

Just in case, check OS timezone setting.

$ timedatect
bash: timedatect: command not found

$ echo $TZ
Asia/Tokyo

$ cat /etc/timezone
Etc/UTC
Enter fullscreen mode Exit fullscreen mode

It is not practical to define the setting in docker-compose.yml as section "2", so, if you need to set timezone, you should set in other places.

Sometimes I found timezone setting as "TZ: UTC" in docker-compose.yml, this setting may not be working, but actually default timezone setting is working.

However, you can reflect timezone setting of docker-compose.yml by stating as below in php.ini.

[Date]
date.timezone = ${TZ}
Enter fullscreen mode Exit fullscreen mode

(note) It is necessary to set php.ini in the container.

Then, the timezone setting of docker-compose.yml is reflected.
Here is the result.

string(10) "Asia/Tokyo"
Enter fullscreen mode Exit fullscreen mode

Summary

  • Timezone of Dockerfile reflects to only OS but not to PHP. It is necessary to set tzone.ini.
  • It is too much work, I personally recommend to set timezone in php.ini.
  • If you want timezone as variable, set docker-compose.yml and pass to php.ini.

When you face to such a situation "Where is the timezone set in this project?", I recommend check "php.ini" first, after that "docker-compose.yml" lastly "Dockerfile".

Extra

You can overwrite timezone using "date_default_timezone_set".

<?php

date_default_timezone_set('Australia/Sydney');

$defaultTimezone = date_default_timezone_get();
var_dump( $defaultTimezone );
Enter fullscreen mode Exit fullscreen mode

Result.

string(16) "Australia/Sydney"
Enter fullscreen mode Exit fullscreen mode

Top comments (0)