容器时区为什么不对
容器内默认时区是 UTC,于是日志时间与业务时间相差 8 小时,是最常见也最容易反复出现的问题。最可预期的方式是设置 TZ 环境变量,但前提是镜像里包含时区数据;精简镜像常常没有时区数据,这时可以挂载宿主机时区文件作为临时方案,或在镜像构建阶段把时区数据装进去。
基本信息
| 方式 A | -e TZ=Asia/Shanghai,镜像内需包含时区数据 |
|---|---|
| 方式 B | 挂载宿主 /etc/localtime 与 /etc/timezone 到容器内 |
| Alpine 差异 | 需先安装时区数据包,再设置 TZ 才生效 |
| 精简镜像 | debian-slim 等同样常缺时区数据,应在构建阶段一并安装 |
| 验证方式 | 在容器内执行 date,并与宿主机 date 对比 |
| 编排建议 | 单容器用环境变量,编排场景在服务定义中统一声明 |
典型使用场景
- 应用日志需要与业务时间一致,便于对账与故障定位
- 定时任务需要按本地时间触发,而不是按 UTC 偏移计算
- 与数据库或中间件交互时排查时间字段不一致的问题
- 跨时区团队协作,统一到同一时区便于比对与沟通
- 容器时间与宿主机对齐,避免监控与日志时间错位
使用示例
使用示例
docker run -d --name app -e TZ=Asia/Shanghai myapp:1.2.3 # 推荐方式
docker exec app date # 验证容器内时间
date # 与宿主对比
apk add --no-cache tzdata # Alpine 内先装时区数据
docker run -d -v /etc/localtime:/etc/localtime:ro nginx:1.27 # 挂载宿主时区文件
docker exec app cat /etc/timezone # 查看容器内时区配置几种方式对比
| 方式 | 生效条件 | 适用与限制 |
|---|---|---|
| 环境变量 TZ | 镜像内有时区数据 | 推荐做法,行为可预期,适合编排统一声明 |
| 挂载宿主时区文件 | 宿主存在对应文件 | 省去改镜像,但依赖宿主环境,跨平台差异大 |
| 构建阶段安装时区数据 | 镜像层内固化 | 一劳永逸,代价是镜像体积略增 |
| 修改容器内时区文件 | 需进入容器操作 | 临时排查可用,容器重建后失效 |
改容器内时区文件只是兜底方案,重启或重建即失效;统一优先使用 TZ 环境变量,行为最可预期,也最容易在编排文件里集中管理,不会因宿主环境不同而漂移。
只设 TZ 却没装时区数据,时间仍然按 UTC 走:环境变量已配置这一事实反而会把人引向其他环节,问题被掩盖,排查成本远高于一开始就验证时区数据是否存在。