Docker/PHP - What is the most prioritized timezone setting?
Tags: docker, php
Published: 2023-04-09 16:03:36

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

**php.ini**
example
```ini
[Date]
date.timezone = "Europe/Madrid"
```

**Dockerfile**
example
```
FROM php:8.1.12-fpm

ENV TZ=America/Los_Angeles
```

**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
```

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
<?php

$defaultTimezone = date_default_timezone_get();
var_dump( $defaultTimezone );
```

## 1. define 3 places, php.ini, Dockerfile and docker-compose.yml
Result.
```
string(13) "Europe/Madrid"
```

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"
```

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
```

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
```

Then, the result of PHP code execution, timezone setting in Dockerfile is reflected.
```
string(19) "America/Los_Angeles"
```

/etc/timezone will be updated.
```
$ cat /etc/timezone
America/Los_Angeles
```

## 3. define 1 places docker-compose.yml
Result.
```
string(3) "UTC"
```
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
```

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}
```
(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"
```

## 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
<?php

date_default_timezone_set('Australia/Sydney');

$defaultTimezone = date_default_timezone_get();
var_dump( $defaultTimezone );
```
Result.
```
string(16) "Australia/Sydney"
```