文章

Typecho 发布文章后前台不显示:Docker PHP 容器时区问题排查与解决

语之溪

·

容器与部署

·

在 Typecho 后台发布文章时,明明已经设置为“公开发布”,但前台首页和文章列表中始终看不到。遇到这种情况,除了缓存和主题筛选,最常见的原因之一就是:

Typecho 判断文章发布时间时,PHP 使用的时区与服务器本地时区不一致,导致文章被当成“未来文章”。

本文以 Docker 部署的 PHP 8.2 容器为例,记录完整的排查和解决过程。

一、问题现象

Typecho 后台能够正常编辑并发布文章,文章权限也设置为公开,但前台不显示。

进入 PHP 容器检查时间:

docker exec php8_2_28 php -r \
'echo date_default_timezone_get(), PHP_EOL, date("Y-m-d H:i:s"), PHP_EOL, time(), PHP_EOL;'

输出如下:

UTC
2026-09-07 02:41:29
1788748889

这说明:

  • PHP 默认时区是 UTC
  • PHP 显示时间为 02:41
  • 当前 Unix 时间戳为 1788748889

与此同时,检查宿主机时间:

date
date -u
timedatectl status

输出如下:

Mon Sep  7 10:42:09 CST 2026
Mon Sep  7 02:42:09 UTC 2026

Local time: Mon 2026-09-07 10:42:10 CST
Universal time: Mon 2026-09-07 02:42:10 UTC
RTC time: Mon 2026-09-07 02:42:10
Time zone: Asia/Shanghai (CST, +0800)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no

二、原因分析

宿主机时间并没有错误。

宿主机显示:

2026-09-07 10:42:10 CST

PHP 容器显示:

2026-09-07 02:42:10 UTC

北京时间比 UTC 时间快 8 小时,因此:

02:42 UTC + 8 小时 = 10:42 CST

它们表示的是同一个时间点。

所以问题不是 Docker 容器的系统时钟不正确,而是:

PHP 默认使用 UTC 时区,而宿主机和 Typecho 使用的是 Asia/Shanghai(UTC+8)。

Docker 容器通常与宿主机共享内核时钟。容器里的 Unix 时间戳和宿主机应该基本相同,只是因为时区设置不同,格式化后的时间看起来相差 8 小时。

因此,不应该在容器中使用 date -s 强行修改时间,而应该统一 PHP 和 Typecho 的时区配置。

三、确认 PHP 配置文件位置

先查看 PHP 当前加载的配置:

docker exec php8_2_28 php --ini

官方 PHP Docker 镜像通常会输出类似内容:

Configuration File (php.ini) Path: /usr/local/etc/php
Loaded Configuration File:         (none)
Scan for additional .ini files in: /usr/local/etc/php/conf.d

重点关注这一行:

Scan for additional .ini files in: /usr/local/etc/php/conf.d

这表示可以把自定义时区配置放到:

/usr/local/etc/php/conf.d/

不同镜像的配置目录可能不同,应以 php --ini 的实际输出为准。

四、临时修改 PHP 容器时区

如果想先确认是不是 PHP 时区导致的问题,可以直接在容器内创建配置文件:

docker exec php8_2_28 sh -c \
'printf "date.timezone=Asia/Shanghai\n" > /usr/local/etc/php/conf.d/99-timezone.ini'

然后重启容器:

docker restart php8_2_28

重新检查 PHP 时间:

docker exec php8_2_28 php -r \
'echo date_default_timezone_get(), PHP_EOL, date("Y-m-d H:i:s"), PHP_EOL, time(), PHP_EOL;'

正常情况下应该输出:

Asia/Shanghai
2026-09-07 10:xx:xx
178874xxxx

也可以通过下面的命令检查 PHP 日期配置:

docker exec php8_2_28 php --ri date

应该能看到:

Default timezone => Asia/Shanghai
date.timezone => Asia/Shanghai

需要注意的是,这种修改方式只是临时方案。如果以后重新创建或更新容器,容器内部手动添加的配置可能会丢失。

五、通过 Docker Compose 持久化配置

推荐在宿主机上创建独立的 PHP 时区配置文件,并挂载到容器中。

1. 创建 PHP 时区配置

进入 docker-compose.yml 所在目录,创建 php-timezone.ini:

date.timezone = Asia/Shanghai

目录结构可以是:

typecho/
├── docker-compose.yml
└── php-timezone.ini

2. 修改 Docker Compose 配置

在 PHP 服务中添加环境变量和配置文件挂载:

services:
  php:
    image: php:8.2-fpm
    container_name: php8_2_28
    environment:
      TZ: Asia/Shanghai
    volumes:
      - ./php-timezone.ini:/usr/local/etc/php/conf.d/99-timezone.ini:ro

如果原来的 PHP 服务已经存在 volumes,只需要追加新的挂载项,不要删除或覆盖原有的数据卷。例如:

services:
  php:
    image: php:8.2-fpm
    container_name: php8_2_28
    environment:
      TZ: Asia/Shanghai
    volumes:
      - ./typecho:/var/www/html
      - ./php-timezone.ini:/usr/local/etc/php/conf.d/99-timezone.ini:ro

其中:

environment:
  TZ: Asia/Shanghai

用于设置容器环境时区,而:

- ./php-timezone.ini:/usr/local/etc/php/conf.d/99-timezone.ini:ro

用于明确设置 PHP 的 date.timezone。

只设置 TZ 不一定能够改变 PHP 的默认时区,因此建议两项同时配置。

3. 重新创建容器

修改 Compose 配置后,重新创建 PHP 容器:

docker compose up -d --force-recreate php

这里的 php 是 Compose 中的服务名,不一定等于容器名 php8_2_28。

如果不确定服务名,可以执行:

docker compose ps

或者:

docker compose config --services

如果修改了 Dockerfile,则需要重新构建:

docker compose up -d --build php

六、是否需要挂载宿主机时区文件

还可以将宿主机的时区文件挂载到容器:

services:
  php:
    environment:
      TZ: Asia/Shanghai
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
      - ./php-timezone.ini:/usr/local/etc/php/conf.d/99-timezone.ini:ro

不过需要注意:

  • /etc/localtime 通常可以正常挂载
  • /etc/timezone 并不是所有 Linux 发行版都存在
  • PHP 最终使用什么时区,仍应通过 date.timezone 明确设置
  • 如果宿主机以后改变时区,挂载 /etc/localtime 也会影响容器

对于固定使用北京时间的 Typecho 站点,核心配置是:

date.timezone = Asia/Shanghai

七、Alpine 镜像缺少时区数据怎么办

有些 Alpine 镜像默认没有安装 tzdata。如果设置 Asia/Shanghai 后报时区相关错误,可以在 Dockerfile 中安装:

FROM php:8.2-fpm-alpine

RUN apk add --no-cache tzdata

ENV TZ=Asia/Shanghai

RUN printf 'date.timezone=Asia/Shanghai\n' \
    > /usr/local/etc/php/conf.d/99-timezone.ini

重新构建并启动:

docker compose build php
docker compose up -d php

Debian 系官方 PHP 镜像通常可以这样配置:

FROM php:8.2-fpm

ENV TZ=Asia/Shanghai

RUN printf 'date.timezone=Asia/Shanghai\n' \
    > /usr/local/etc/php/conf.d/99-timezone.ini

如果镜像中确实缺少时区数据库,再安装 tzdata:

RUN apt-get update \
    && apt-get install -y --no-install-recommends tzdata \
    && rm -rf /var/lib/apt/lists/*

八、检查 Typecho 的时区设置

修正 PHP 时区后,还要检查 Typecho 后台的站点时区。

进入:

Typecho 后台 → 设置 → 基本

将时区设置为:

Asia/Shanghai

或者选择对应的:

UTC+8

建议让以下配置保持一致:

配置层级推荐值
宿主机时区Asia/Shanghai
Docker 容器环境变量TZ=Asia/Shanghai
PHP date.timezoneAsia/Shanghai
Typecho 后台时区Asia/Shanghai 或 UTC+8

九、修复已经发布但不可见的文章

修改 PHP 时区不会自动修正数据库里已经保存的文章发布时间。

如果之前发布文章时使用了错误的时区,该文章可能已经被写入了一个晚于当前时间的发布时间。Typecho 会将它当成“未来文章”,因此前台不会展示。

解决方法:

  1. 进入 Typecho 后台。
  2. 打开对应文章。
  3. 将发布时间改为当前时间之前一两分钟。
  4. 确认文章状态为“公开”。
  5. 重新发布或保存文章。
  6. 清理页面缓存、CDN 缓存和主题缓存。

例如当前时间是:

2026-09-07 10:42

可以把文章发布时间设置为:

2026-09-07 10:40

然后重新发布。

十、最终验证

配置完成后,可以一次性检查宿主机、容器和 PHP 时间。

检查宿主机:

date
date -u
date +%s

检查容器:

docker exec php8_2_28 date
docker exec php8_2_28 date +%s

检查 PHP:

docker exec php8_2_28 php -r \
'echo "Timezone: ", date_default_timezone_get(), PHP_EOL;
echo "Datetime: ", date("Y-m-d H:i:s"), PHP_EOL;
echo "Timestamp: ", time(), PHP_EOL;'

预期输出类似:

Timezone: Asia/Shanghai
Datetime: 2026-09-07 10:42:10
Timestamp: 1788748930

宿主机和容器的 Unix 时间戳应该基本相同,最多相差几秒。

需要特别说明的是:

RTC time: UTC
RTC in local TZ: no

这是 Linux 推荐的正常配置,不需要修改。硬件时钟使用 UTC,操作系统再根据 Asia/Shanghai 转换成本地时间,可以避免夏令时和跨时区带来的问题。

总结

Typecho 后台发布文章后前台不显示,可能是 PHP 时区与站点时区不一致造成的。

本次问题中:

  • 宿主机时间正常
  • NTP 同步正常
  • Docker 容器时钟正常
  • PHP 默认时区为 UTC
  • Typecho 使用北京时间,产生了 8 小时的时间判断偏差

最终解决方案是在 PHP 中明确设置:

date.timezone = Asia/Shanghai

同时在 Docker Compose 中配置:

environment:
  TZ: Asia/Shanghai

并通过配置文件挂载实现持久化:

volumes:
  - ./php-timezone.ini:/usr/local/etc/php/conf.d/99-timezone.ini:ro

修复后,再将受影响文章的发布时间调整到当前时间之前并重新发布,文章即可正常显示。

现在已有 66 次阅读,0 条评论,0 人点赞
作者:语之溪
作者
Typecho 发布文章后前台不显示:Docker PHP 容器时区问题排查与解决
当前文章累计共 7211 字,阅读大概需要 4 分钟。
微服务拆分时,服务边界应该如何确定
2026年1月10日 - 0评论
问题复测中的数字为什么不能随意统一
2024年3月16日 - 0评论
我第一次接触 ChatGPT
2023年6月24日 - 0评论
评论:共0条
发表
功能 探索 消息

足迹

你还不曾留下足迹..

音乐单

随机文章

夜晚

💬
你还不曾留言过
博主 不再显示
博主
未知作品 歌曲封面
立即安装