frankenphp容器默认使用utc时区,需挂载/etc/localtime和/etc/timezone并设置tz环境变量,或在dockerfile中预置时区文件;php代码层还需调用date_default_timezone_set()确保时间处理正确。

FrankenPHP容器启动后date命令仍显示UTC时间
FrankenPHP基于Swoole和PHP-FPM混合模型,但它的基础镜像(如frankenphp:latest)默认不设本地时区,仍用UTC。你执行date看到的是UTC时间,不是容器“坏了”,而是没告诉它你在东八区。
验证方式:进容器运行date && cat /etc/timezone 2>/dev/null || echo "no /etc/timezone"。如果输出类似Sat Oct 4 05:56:23 UTC 2026且无/etc/timezone内容,就确认是纯UTC环境。
- 不要只改
TZ环境变量——FrankenPHP的底层PHP进程不读TZ,它依赖系统级时区文件 - 必须挂载
/etc/localtime或在Dockerfile里预置,否则date()、DateTime构造、日志时间戳全按UTC走 - Alpine系镜像(如
frankenphp:alpine)默认不含tzdata包,光设TZ环境变量无效
Docker run时同步宿主机时区最简方案
适用于调试、CI/CD临时部署或无法改Dockerfile的场景。一条命令搞定:
docker run -d \ -v /etc/localtime:/etc/localtime:ro \ -v /etc/timezone:/etc/timezone:ro \ -e TZ=Asia/Shanghai \ --name my-frankenphp \ ghcr.io/dunglas/frankenphp
注意三个挂载/设置缺一不可:
-
/etc/localtime只读挂载:让C库localtime()等系统调用返回正确时间 -
/etc/timezone只读挂载:部分PHP扩展(如intl)依赖此文件识别时区名 -
TZ=Asia/Shanghai:补位,避免某些busybox/sh环境下date命令 fallback 到TZ
验证:进容器执行php -r "echo date('Y-m-d H:i:s');",应输出北京时间而非UTC时间。
Dockerfile构建时固化时区(推荐生产)
FrankenPHP官方镜像不预设时区,所以你要自己构建一层。关键点不是“加一行ENV”,而是确保/etc/localtime是真实软链且指向有效时区数据:
FROM ghcr.io/dunglas/frankenphp:1.2 <h1>Alpine用户必须先装tzdata</h1><p>RUN apk add --no-cache tzdata && \ cp -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ echo "Asia/Shanghai" > /etc/timezone</p><h1>Debian/Ubuntu用户可简化为:</h1><h1>RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \</h1><h1>echo "Asia/Shanghai" > /etc/timezone</h1>
构建后验证:docker build -t my-frankenphp . && docker run --rm my-frankenphp date 输出应含CST或GMT+8字样。
- 别用
RUN export TZ=Asia/Shanghai——这是shell变量,不写入文件,容器启动后失效 - 别用
PRC别名——FrankenPHP用的PHP版本(≥8.2)已弃用该标识,Asia/Shanghai才是IANA标准 - 构建镜像后,
docker inspect查Config.Env不会显示时区,但date命令会正确
PHP代码层仍要设date_default_timezone_set()
即使容器系统时间已正确,FrankenPHP的PHP进程默认仍可能用UTC解析字符串。比如strtotime('2026-10-04')若没设时区,会当成UTC时间处理,导致入库值偏移。
在FrankenPHP应用入口(如public/index.php顶部)加:
<?php date_default_timezone_set('Asia/Shanghai');
// 后续所有 date(), DateTime(), strtotime() 都按北京时间解析
?>
这个设置不能省,原因有二:
- FrankenPHP的PHP子进程不继承容器
/etc/localtime对PHP内部时区逻辑的影响 - 数据库连接(如PDO)仍需显式执行
SET time_zone = '+08:00',否则NOW()函数返回UTC
最容易被忽略的是:你看到date()输出对了,就以为万事大吉——但DateTime::createFromFormat('Y-m-d', '2026-10-04')若没设默认时区,依然按UTC构造对象。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











