当前位置:首页 >  IDC >  服务器 >  正文

Docker容器默认UTC时区,应用日志与东八区相差8小时

 2026-10-31 15:04  来源: 互联网   我来投稿 撤稿纠错

  一键部署OpenClaw

对账脚本的时间对不上,订单表的创建时间是2026-10-24 10:15:22,应用日志里同一笔写的是02:15:22。两边差了整整八小时,宿主机上date输出的时间是准的。

容器启动时如果没有显式指定时区,多数官方基础镜像里也没有/etc/localtime这个文件,glibc找不到就退回UTC。日志里的时间由应用自己生成,取的是容器内的时间,于是整批记录都往前提了八小时。docker logs看到的时间戳不一定可信,它默认照抄应用输出,应用写UTC它就显示UTC,加--timestamps才是dockerd自己打的时间戳,格式固定为UTC带Z后缀,和容器时区无关。宿主机准不代表容器准,这两套是分开的。

做法有三种,挂载宿主机的/etc/localtime到容器同名路径并加只读参数,设置TZ环境变量,在镜像里装tzdata再把TZ写进Dockerfile。三种都能达到目的,前提各不相同,选哪种看部署方式和基础镜像。

TZ这一条有前提。基于glibc的镜像认这个变量,debian、ubuntu、centos都行;glibc是这类镜像默认的C运行库,时区数据由它读取。基于alpine的镜像用的是musl,镜像里默认不带时区数据,export TZ=Asia/Shanghai之后date还是UTC,得先apk add tzdata。这一条踩过好几次,同一个compose文件,换了基础镜像就失效,日志里的时间又回去了。挂载localtime的做法不依赖libc,alpine下也能用,缺点是容器跟宿主机绑在一起,换一台机器就得记得重新挂。

还有一种情况完全绕开容器时区,应用自己在配置里写死了时区,PHP的date.timezone、Java的user.timezone都算,这类写死在应用配置里之后,容器改对了也不跟着变。PHP的话,php.ini里的date.timezone一旦写上Asia/Shanghai,date()和date_default_timezone_get()都按它走,跟容器里的UTC无关。MySQL容器还多一层,它有自己的time_zone参数,默认是SYSTEM,跟容器时区走,写进my.cnf之后就跟容器无关了。

验证不用猜,你进容器执行date,输出带UTC还是带CST一目了然。再看一眼/etc/localtime是不是软链,以及php -i里date.timezone那一行。三处里有一处不对,日志和数据库就会各说各话,误差固定是八小时。

改宿主机时区是不对的,宿主机上的其他服务、日志轮转、证书校验都按它走,为了一个容器动全局,代价不成比例。真要统一,就在镜像层面把tzdata和TZ都打进去,一次做完,之后换机器不用再改。

现在compose里挂载localtime,同时保留TZ变量,镜像换成alpine时也有tzdata兜底。定时任务这块要单独核对,容器里的crond按容器时区算,写着0 2 * * *的任务,实际在本地时间上午十点跑。对账、报表、备份这类按点执行的任务,改完时区之后要重新对一遍执行时间,别只看日志时间对了就以为全对。跨时区的日志检索也顺手改掉,之前按字符串比较时间做的报警规则全部要重写,否则阈值判断会整批偏移。

申请创业报道,分享创业好点子。点击此处,共同探讨创业新机遇!

相关标签
docker
时区

相关文章

  • 环境配一次崩一次?Docker一条命令拉起LNMP,搬家不再从零开始

    传统装LNMP的痛,装过的都懂:PHP版本、扩展依赖、MySQL配置,换台服务器全部重来一遍,中途各种版本冲突。Docker把整套环境固化成配置文件,机器挂了,新机器上dockercomposeup一条命令,几分钟恢复原样。核心概念就三个:镜像(环境模板)、容器(跑起来的实例)、卷(挂出来的数据目录

    标签:
    php教程
    docker
  • 保姆级 NAS docker 部署 Openclaw 并接入飞书,海康教程

    小龙虾的风愈演愈热。之前我发了不少使用虚拟机、PC的部署OpenClaw的教程,但是一直没有发docker版本的教程。其实最主要的原因就是docker版本在最开始的部署太麻烦了。而且1月底那会儿,我自己对OpenClaw的理解也没那么深入。现在再回过头去看OpenClaw的docker版本,发现其实

    标签:
    NAS
    docker

热门排行

信息推荐