容器里执行 date 显示的是 UTC,日志时间比本地早八小时,定时任务也跟着错位。镜像默认用 UTC,不改就是差八小时。
先确认容器里的时间
docker exec -it 容器名 date docker exec -it 容器名 cat /etc/timezone
输出里出现 UTC 就说明时区没设。注意宿主机时间正确不代表容器正确,两者是独立的。
运行参数里直接指定
docker run -d \ -e TZ=Asia/Shanghai \ -v /etc/localtime:/etc/localtime:ro \ 镜像名
环境变量 TZ 需要镜像内有 tzdata 才生效。精简镜像往往没有,挂载宿主机的 localtime 更稳,两种方式一起用最省心。
写进 Dockerfile 和 compose
ENV TZ=Asia/Shanghai RUN apk add --no-cache tzdata || apt-get update && apt-get install -y tzdata
compose 里对应 environment 加一行 TZ 即可。已经有容器在跑时,改配置后要重新创建容器,restart 不会应用新的挂载。
应用层也要同步,比如 Java 的 -Duser.timezone、Python 的 TZ 环境变量,否则数据库里存的时间还是错的。
验证方式和常见遗漏
docker exec -it 容器名 date "+%F %T %Z"
输出里带 CST 或 +0800 才算对。有些基础镜像虽然设了 TZ,但缺少 zoneinfo 文件,date 仍然显示 UTC,这时挂载宿主机的时区文件最直接。
日志采集链路也要一起看:容器时间对了,日志平台仍按 UTC 展示,排查时又会误判。数据库连接串里如果显式指定了时区参数,应用写入和查询的时间可能再差一轮,建议统一用带时区的时间类型存储。
最后提醒一句,容器里不要用改 /etc/localtime 的手工方式持久化,重建容器就没了,配置要写进镜像或编排文件。