朕喜技术(ZhenxiJS)
2026.09.01
1 分钟阅读

Docker 容器时区不一致导致定时任务/日志时间错乱 — 排查与修复实战

问题背景

某团队将 Python 定时报表系统打包进 Docker 容器部署,业务要求每天北京时间(CST,UTC+8)09:00 生成并发送日报。部署后发现两个问题:

  1. 日志时间比真实时间慢了 8 小时:容器内显示 2026-09-01 01:00:00,实际北京时间已是 2026-09-01 09:00:00。
  2. 定时任务偏移:每天 09:00 触发的日报任务,实际在北京时间 17:00 才触发(即容器里的 09:00)。

根本原因:Docker 容器默认使用 UTC 时区,未配置为东八区。

复现步骤

# 克隆仓库并切换到对应分支
git checkout 2026-09-01-0000

# 启动复现环境
cd scenario/2026-09-01-0000
docker compose up -d --build
docker compose exec app bash

# 查看容器时区——输出为 UTC
date
# Mon Aug 31 16:06:32 UTC 2026

# 查看时区文件
readlink -f /etc/localtime
# /usr/share/zoneinfo/Etc/UTC

# 运行时间检查脚本
python3 /app/check_time.py
# >>> 容器时区不是东八区(当前偏移 +0 小时)✗

根本原因

Docker 容器默认时区为 UTC,具体原因包括:

  1. 未设置 TZ 环境变量:Docker 容器继承镜像默认配置,python:3.11-slim 默认 UTC。
  2. 未修改系统时区文件:/etc/localtime 指向 Etc/UTC,/etc/timezone 文件不存在。
  3. Python datetime.now() 读取系统时区:由于系统时区为 UTC,返回的时间偏移 8 小时。
  4. 定时任务(cron / APScheduler / 自定义调度器)同样受影响:所有基于系统时间的逻辑都会偏移。

解决办法

方案一:Dockerfile 中设置(推荐)

FROM python:3.11-slim

# 安装 tzdata(python:3.11-slim 默认不含)
RUN apt-get update && apt-get install -y --no-install-recommends tzdata \
    && rm -rf /var/lib/apt/lists/*

# 设置 TZ 环境变量
ENV TZ=Asia/Shanghai

# 修改系统时区文件
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
    && echo "Asia/Shanghai" > /etc/timezone

方案二:docker-compose.yml 中设置

services:
  app:
    image: your-image
    environment:
      - TZ=Asia/Shanghai

方案三:运行时手动修复(临时)

# 进入容器后执行
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo "Asia/Shanghai" > /etc/timezone
export TZ=Asia/Shanghai

验证

# 1. date 命令显示 CST
$ date
Tue Sep  1 00:17:59 CST 2026

# 2. Python datetime.now() 返回北京时间
$ python3 -c "from datetime import datetime; print(datetime.now())"
2026-09-01 00:17:59.123456

# 3. 时区偏移正确
$ python3 -c "import time; print(time.timezone / 3600)"
-8  # 即 UTC+8

经验与避坑指南

关键要点

  1. Docker 容器默认时区是 UTC,不是宿主机时区。部署任何依赖时间的应用时,必须显式配置时区。
  2. ENV TZ=Asia/Shanghai 是最简单可靠的方案,Python 的 datetime.now() 会自动读取。
  3. 需要安装 tzdata 包,否则 ENV TZ 可能不生效(尤其 slim/alpine 镜像)。
  4. /etc/localtime 和 /etc/timezone 都要修改,确保 date 等系统命令正确显示。

常见报错与排查技巧

现象排查命令可能原因
date 显示 UTCreadlink -f /etc/localtimelocaltime 指向 Etc/UTC
Python 时间偏移 8hecho $TZTZ 环境变量未设置
/etc/timezone 不存在cat /etc/timezone未配置 timezone 文件
cron 任务不准时date + crontab -lcron 使用系统时区

其他注意点

  • Node.js 应用同样受容器时区影响,new Date() 会返回 UTC 时间。
  • Java 应用可通过 -Duser.timezone=Asia/Shanghai 设置。
  • cron 使用系统时区(/etc/localtime),仅设置 TZ 环境变量可能不够。
  • 生产环境建议在 CI/CD 构建阶段就在镜像中固定时区,而非运行时依赖外部环境变量。

可复现命令

# 完整验证流程
git checkout 2026-09-01-0000
cd scenario/2026-09-01-0000
docker compose up -d --build
docker compose exec app bash -c '
  date
  readlink -f /etc/localtime
  cat /etc/timezone
  python3 /app/check_time.py
'

技术栈

Docker、docker-compose、Python 3.11、timezone、TZ 环境变量、UTC、CST、Asia/Shanghai、cron 定时任务、datetime.now()

版权声明

本文为博主原创文章,遵循 CC BY-NC-SA 4.0 许可协议。 转载请注明出处:http://localhost/blogs/2026-09-01-0018

分享这篇文章