故障现象
容器内时间,已经通过 ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
修正好了。
root@094bd0f1b1b2:/usr/local/tomcat# date
Fri Jan 13 11:09:02 AM CST 2023
root@e41641d35798:/usr/local/tomcat# date +%Z
CST
root@e41641d35798:/usr/local/tomcat# date +'%:z %Z'
+08:00 CST
root@e41641d35798:/usr/local/tomcat# ll /etc/localtime
lrwxrwxrwx 1 root root 33 Jan 13 13:18 /etc/localtime -> /usr/share/zoneinfo/Asia/Shanghai
root@e41641d35798:/usr/local/tomcat# cat /etc/timezone
Etc/UTC
root@e41641d35798:/usr/local/tomcat# echo $TZ
但是,docker logs 显示时间仍然不正常
2023-01-13 03:07:50.363 INFO 1 --- [nio-8080-exec-1] c.s.lis.pubfun.OptimisticLockDataCheck : 不做校验
2023-01-13 03:07:50.398 INFO 1 --- [nio-8080-exec-1] c.s.lis.pubfun.OptimisticLockDataCheck : 不做校验
2023-01-13 03:07:50.404 INFO 1 --- [nio-8080-exec-1] c.s.lis.pubfun.OptimisticLockDataCheck : 不做校验
JVM怎么获取timezone信息
- JVM uses the environment variable
TZ
if it is set. - If TZ is not set, then JVM looks for the file
/etc/sysconfig/clock
and finds theZONE
entry. - If neither
TZ
norZONE
is set, JVM compares the contents of/etc/localtime
to the files in/usr/share/zoneinfo
looking for a match. The matching path and filename under/usr/share/zoneinfo
provides the time zone.
故障分析
Java 在 unix 系统下如何判断 time zone ? 翻译如下
当没有设置 TZ
环境变量的时候, POSIX specification 并没有指定如何判断 timezone 。我在 Linux Standard Base 上没有找到相关资料。 base system library (GNU libc) 使用 /etc/localtime
来判断 timezone。在非嵌入式Linux上,/etc/localtime
是存储 timezone 信息的地方,理想情况这个故事就到此结束了。
(然而, FreeBSD 、NetBSD 、 OpenBSD 使用 /etc/localtime
。 Solaris 还有一些其他系统使用 /etc/TIMEZONE
。参考 Rosetta Stone for Unix , Dietlibc (used in some embedded Linux systems) 使用 /etc/localtime
, uClibc 使用 /etc/TZ
(unless patched).)
然而,Java 不是这么做的。Debian 和 Ubuntu 有一个 /etc/timezone
文件保存 timezone 的信息。这个文件用于系统打包,这样它就可以记住像Europe/Amsterdam
这样的地理名称,而不仅仅是时区的描述(比如:CET、CEST和CEDT)。这不仅对利于人类理解,而且在更新地理区域设置时更坚实。Sun (现在是 Oracle) Java 偏向使用 /etc/timezone
(Red Hat发行版对应于 /etc/sysconfig/clock
) see bug #6456628 而不是 /etc/localtime
, OpenJDK 和 gcj 随之效防。
参考:
How do I find the current system timezone?
Java Time Zone is messed up.
解决方案很简单:同时更新 /etc/timezone
和 /etc/localtime
文件。在 Debian 和 Ubuntu上, 官方推荐使用 dpkg-reconfigure tzdata
。只对一个应用设置时区,设置 TZ
环境变量即可 (在所有unix平台适用)。
解决方案
echo "Asia/Shanghai" > /etc/timezone
dpkg-reconfigure -f noninteractive tzdata
sudo ln -fs /usr/share/zoneinfo/Europe/Dublin /etc/localtime
sudo dpkg-reconfigure -f noninteractive tzdata
Dockerfile 范例
FROM tomcat:9.0.69-jdk8-temurin
VOLUME $CATALINA_HOME/logs
ARG WAR_FILE=target/*.war
COPY $WAR_FILE ./webapps/
COPY ./docker-entrypoint.sh .
RUN set -eux; \
\
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && dpkg-reconfigure -f noninteractive tzdata; \
chmod +x ./docker-entrypoint.sh
EXPOSE 8080
ENTRYPOINT ["./docker-entrypoint.sh"]
CMD ["catalina.sh", "run"]
网友评论