Docker 容器时区问题:UTC 导致的自然日业务刷新异常

目录

最近将微信小程序后端迁移到 Docker 后,出现了“每日刷新”相关 Bug,例如:

  • 每日广告次数未刷新
  • 次日仍然沿用前一天状态

排查后发现,问题并不在业务逻辑,而是:

  • Docker 容器默认使用 UTC 时区。

而业务中的“每日刷新”逻辑实际上是基于东八区自然日实现的。

例如:

1
2
if user.last_ad_time != today:
    user.today_ad_views = 0

当中国时间已经进入第二天时:

中国时间UTC 时间
2026-05-19 00:302026-05-18 16:30

后端仍然认为“还是昨天”,从而导致自然日逻辑整体延迟 8 小时。


最终方案

数据库存储统一使用 UTC

数据库中的 datetime / timestamp 统一存 UTC。

优点:

  • 避免时区混乱
  • 避免夏令时问题
  • 多服务容易统一

前端负责本地化显示

后端返回 UTC:

前端按用户本地时区格式化:

1
new Date(utcTime).toLocaleString()

自然日业务明确业务时区

像:

  • 每日限额
  • 定时刷新

这类逻辑本质上依赖“业务时区”。

对于面向中国用户的服务,直接统一:

1
ENV TZ=Asia/Shanghai

通常是最简单稳定的方案。

精简镜像中的 tzdata 问题

如果使用 Alpine / slim 等精简镜像:

则可能需要额外安装:

1
RUN apk add --no-cache tzdata ca-certificates

总结

目前采用的时间处理策略:

层级策略
数据库存储UTC
前端显示用户本地时区
后端 Docker 容器TZ=Asia/Shanghai

发现新版本

当前站点有新版本可用。