Docker 部署后文章发布时间变成 UTC 的排查与修复


文章封面

Docker 部署后文章发布时间变成 UTC 的排查与修复

最近在 Docker 部署 YESCMS,并使用 PostgreSQL 数据库时,发现后台发布文章后的时间不对:页面显示出来的时间像是按 UTC 来算的,比本地时间少了 8 个小时。

这个问题看起来像数据库时区问题,但真正排查下来,根因在容器运行环境。

现象

本地开发环境发布文章,时间正常。

部署到 Docker 后,发布文章的时间会偏向 UTC。例如北京时间下午发布,页面上显示出来却像是早上。

项目里的文章发布时间使用的是类似这样的写法:

create_time = DateTime.Now,
update_time = DateTime.Now,

这段代码本身没有做 UTC 转换。它取的是当前运行环境的本地时间。

根因

Docker 容器默认时区通常是 UTC。

所以问题不是 PostgreSQL 主动把时间改成了 UTC,也不是页面展示时强行转换了时区,而是应用运行在容器里时,DateTime.Now 拿到的“本地时间”本来就是 UTC。

换句话说:

DateTime.Now 取的是容器时间
容器默认是 UTC
所以写入数据库的时间就是 UTC 风格的时间

PostgreSQL 里如果字段使用 timestamp without time zone,它只是存储一个日期时间值,不会替你记住这个值到底属于哪个时区。应用写进去什么,它就保存什么。

不建议到处改业务代码

遇到这个问题,最直接的反应可能是把代码改成:

DateTime.UtcNow.AddHours(8)

这不推荐。

原因很简单:这会把“中国时区”硬编码进业务代码。以后如果部署到其它地区,或者同一个镜像给不同地区使用,就会继续产生新的时间问题。

更好的做法是让运行环境告诉应用:当前部署到底使用哪个时区。

推荐修复方式

docker-compose.yml 里给应用容器加上 TZ 环境变量:

services:
  yescms:
    environment:
      ASPNETCORE_ENVIRONMENT: Production
      ASPNETCORE_URLS: http://+:8080
      TZ: Asia/Shanghai

这样处理后,容器内的本地时间会按 Asia/Shanghai 计算,DateTime.Now 获取到的就是北京时间。

如果以后部署到其它地区,只需要改 compose 里的 TZ

TZ: America/Los_Angeles

不需要重新改代码,也不需要把 Docker 镜像固定成某个国家或地区的时区。

为什么不直接写进 Dockerfile

也可以在 Dockerfile 里设置:

ENV TZ=Asia/Shanghai

但这样会让镜像默认固定为中国时区。

如果这个镜像只在中国服务器上运行,问题不大;但如果以后镜像可能部署到国外服务器,固定在 Dockerfile 里就不够灵活。

所以更稳妥的做法是:

镜像保持通用
部署环境通过 docker-compose.yml 指定时区

这也是配置和镜像职责分离的做法。

修改后如何生效

修改 docker-compose.yml 后,需要重建或重启容器:

docker compose up -d --build

如果使用的是远程镜像,且没有重新构建镜像,也可以直接重建容器:

docker compose up -d

然后进入容器检查时间:

docker exec -it yescms date

如果输出的是北京时间,说明容器时区已经生效。

旧文章时间怎么办

这个修复只影响后续新写入的数据。

已经写入数据库的旧文章时间不会自动修正。因为数据库里保存的是一个普通日期时间值,系统无法可靠判断哪些记录是 UTC 写入、哪些记录本来就是正确时间。

如果确定某一批旧数据全部都是 UTC 错误时间,可以在备份数据库后,单独写 SQL 批量加 8 小时。但这个操作会直接修改历史数据,应该先确认范围,再执行。

总结

Docker 部署后文章发布时间显示成 UTC,本质上是容器默认时区导致的。

对于使用 DateTime.Now 的应用,最简单、最稳的修复方式是在部署层指定时区:

TZ: Asia/Shanghai

不要把时区补偿写死到业务代码里,也不要轻易把通用镜像固定成某一个地区的时区。把时区放在 compose 配置里,既能解决当前问题,也方便以后迁移到其它地区部署。

版权声明:本文为YES开发框架网发布内容,转载请附上原文出处连接
MCP自动发表文章
上一篇:VS Code 源代码管理里的 Git 标记是什么意思?
下一篇:没有了
评论列表

发表评论

评论内容
昵称:
验证码:
验证码
关联文章

Docker 部署文章发布时间变成 UTC 排查修复
Rocky Linux 虚拟机磁盘扩容 lsblk 没变化排查处理
YES-CMS 内容管理系统 快速发布部署
记一次.Net Core程序启动失败排查过程
C# .net项目Docker方式部署
使用.NET 6开发TodoList应用(30)——实现Docker打包和部署
C# 时间 标准时间互转
Docker 私有镜像仓库 二:Harbor部署
.NET Core发布IIS部署无法访问静态文件
YESCMS MCP 插件配置教程:让 AI 工具直接发布文章
发布,登录界面不见了elementUI节点
用 Jenkins 通过 SSH 自动部署 Docker 服务,同时确保服务器安全
Docker 私有镜像仓库 一:Docker Registry
JAVA环境部署
解决VUE发布因为浏览器缓存造成页面没更新问题
你通过 docker-compose.yml 启动了 MySQL 容器,更改了 .yml 中默认密码,但执行 docker-compose up -d 发现并没有生效
一劳永逸,解决.NET发布云服务器时区问题
C# Abp框架入门系列文章(一)
手把手教你学Dapr - 6. 发布订阅
《步步入门》 .NET 6 部署到Linux

联系我们
联系电话:15090125178(微信同号)
电子邮箱:garson_zhang@163.com
站长微信二维码
微信二维码