部署服务后,用Docker容器化操作常会遇到时区等小麻烦,下面我就来谈谈如何应对这些问题。
问题初现
[apiuser@xygerp-api software]$ date
2018年 04月 24日 星期二 15:00:05 CST
部署Docker容器时遇到了一个小问题,需要记录服务的预定启动时间。发现多份记录的时间差达到了8小时,这显然是时区设置不当所致。考虑到我使用的是容器化部署,首先猜测是Docker的时区配置出了问题。然而,经过检查,主机的时区设置并无异常,这让我对问题的根源感到困惑。
sudo docker run --name timezone-test -p 8800:8080 -v /etc/localtime:/etc/localtime chaimm/tomcat:1.1
排查容器时区
[apiuser@xygerp-api software]$ sudo docker exec -it timezone-test /bin/sh
sh-4.2$ date
Tue Apr 24 15:05:14 CST 2018
我使用exec命令进入容器,检查了容器内的时钟设置。从表面上看,时区设置没有问题。然而,运行在容器中的Tomcat服务却有些异常。无论是操作数据库的时间,还是Tomcat的日志时间,都显示为UTC。这让人感到困惑,因为容器时区设置正确,为何Tomcat服务却显示为UTC时间,让人难以理解。
24-Apr-2018 07:03:55.381 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /opt/tomcat/webapps/host-manager
24-Apr-2018 07:03:55.410 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /opt/tomcat/webapps/host-manager has finished in 29 ms
24-Apr-2018 07:03:55.410 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /opt/tomcat/webapps/manager
24-Apr-2018 07:03:55.431 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /opt/tomcat/webapps/manager has finished in 21 ms
24-Apr-2018 07:03:55.437 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler [http-nio-8080]
24-Apr-2018 07:03:55.447 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler [ajp-nio-8009]
24-Apr-2018 07:03:55.450 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 886 ms
不同时区确认
确认数据库时区操作简便,只需执行“select now()”命令即可。然而,Java的JDBC在添加数据时,并不依据MySQL的时区设置,而是依据操作系统的时区。比如,若系统安装时选择了中国上海的时区,通常显示为CST(中国标准时间)。如有疑问,可以进入容器执行命令来检查时区设置。
Java与JVM时区关系
Tomcat是一款用于运行Java Web应用的服器,其时区设置与JVM的时区一致。在Java程序中,时区的处理主要依赖于JVM启动时的时区设置。通常情况下,JVM会默认采用操作系统的时区。然而,要准确知道JVM默认启动的时区是哪一个,又成为一个新的挑战。
确认JVM默认时区
我编译并执行了相关代码来观察输出,以此确定JVM默认使用的时区设置。尽管在Docker容器中将系统时间调整为CST时区,但使用System.getProperty(“user.timezone”)查询时,却显示为UTC时区。这导致Java程序在启动时,是以UTC时区来运行的。宿主进行同样的操作,却能够准确获取时区信息,这一现象在Docker容器环境中尤为明显。
sh-4.2$ vi TestTimezone.java
public class TestTimezone{
public static void main(String[] args){
System.out.println(new java.util.Date());
System.out.println(System.getProperty("user.timezone"));
}
}
解决时区问题
sh-4.2$ javac TestTimezone.java
sh-4.2$ java TestTimezone
Tue Apr 24 07:27:30 UTC 2018
UTC
既然是在Docker容器中,System.getProperty(“user.timezone”)获取的时区值并非CST所致。那么,一个简便的方法就是在Tomcat启动时明确设定时区。这同样是一种解决途径。我们还可以通过调整Docker容器中System.getProperty(“user.timezone”)参数的设定,确保JVM在启动时能够准确识别时区。起初,我以为问题出在Docker容器虚拟机的时区设置上,但后来发现,只要在启动容器时正确指定时区,问题就能得到解决。
使用Docker容器部署服务时,你是否遇到过时区相关的困扰?如有同感,不妨在评论区留言。若觉得文章对您有所帮助,请点赞并分享。
[apiuser@xygerp-api software]$ java TestTimezone
Tue Apr 24 15:31:03 CST 2018
Asia/Shanghai
发表回复