Docker容器中的OpenJDK 1.8.0与/ etc / timezone和主机有不同的时区

我有一个运行TomEE的Docker容器的Linux机器,运行一个我构build的WAR。

在基本的Linux机器上,我得到一个“date”值“2017年1月20日10:37:27 PST 2017”。 TZ环境variables未设置。

当我运行以下类:

import java.util.Date; import java.util.TimeZone; public class DatePrint { public static void main(String[] args) { System.out.println("date[" + new Date() + "] tzoffset[" + TimeZone.getDefault().getOffset(new java.util.Date().getTime()) + "]"); } } 

我得到这个:

 date[Fri Jan 20 10:39:02 PST 2017] tzoffset[-28800000] 

这一切都很好。

在我的Docker容器上运行,其中我有“-v / etc / localtime:/ etc / localtime”作为一个卷映射,我显然有相同的/ etc / localtime文件。 TZ环境variables未设置。 当我在容器中运行“date”时,我在同一个时区(PST)中得到一个与基本主机相同的时间值。

然后我编译并运行与上面相同的Java类,并得到以下结果:

 date[Fri Jan 20 18:30:38 UTC 2017] tzoffset[0] 

然后手动设置容器中的TZ环境variables(记住它没有在基本主机中设置)为“America / Los_Angeles”(我通过查看“/ etc / localtime”符号链接到的文件来validation该值主办)。

然后,我重新在容器上的类,得到这个:

 date[Fri Jan 20 10:35:08 PST 2017] tzoffset[-28800000] 

请注意,基本主机和容器上的两个Java版本几乎完全相同。 它们都是OpenJDK 1.8.0_111(主机上的b15,容器上的b14)。

那么,有人可以解释一下这里发生了什么吗? 在基本的主机上,我有“etc / localtime”指向正确的文件,但我没有TZ设置。 它用“date”和Java类报告正确的时区。 在容器上,“/ etc / localtime”指向正确的文件,而我原本没有TZ设置。 “date”命令返回正确的值,但Java没有。

我必须手动将容器上的TZ设置为来自主机的TZ值,并使其工作。 我宁愿不这样做。 这对我来说似乎是一个黑客。

更新

我在“localtime(5)”手册页中注意到了以下内容:

由于时区标识符是从/ etc / localtime的符号链接目标名称中提取的,因此该文件可能不是普通文件或硬链接。

所以,这可能是我的问题的一部分。 仍然好奇的是从shell的“date”工作正常,但Java(没有TZ设置)变得困惑。

我和你有同样的问题(CentOS,Docker,OpenJDK)。 我们这样解决它:

不要挂载本地时间,挂载/ etc / timezone。

如果你没有/ etc / timezone文件(比如在CentOS上),你可以这样做(在主机上):

 timedatectl | awk '/Time zone:/ {print $3}' > /etc/timezone_host 

然后在容器(例如入口点)

 TZ_HOST=$(cat /etc/timezone_host) echo $TZ_HOST > /etc/timezone export TZ=$TZ_HOST dpkg-reconfigure --frontend noninteractive tzdata 

也许转储环境(env命令),LC_ *(LC_ALL通常)可以影响它。