Docker容器中的OpenJDK 1.8.0与/ etc / timezone和主机

时间:2017-01-20 18:48:42

标签: java linux docker timezone

我有一个运行Docker容器的Linux机器人,它正在运行TomEE,并运行我构建的WAR。

在Linux基本框上,我得到的“日期”值为“2017年1月20日10:37:27太平洋标准时间2017”。未设置TZ环境变量。

当我运行以下课程时:

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环境变量。当我在容器中运行“date”时,我在与基本主机相同的时区(PST)中获得时间值。

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

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

然后我手动将容器中的TZ环境变量(请记住它未在基本主机中设置)设置为“America / Los_Angeles”(我通过查看“/ etc / localtime”符号链接到的文件来验证此值在基础主机上。)

然后我在容器上重新上课并得到了这个:

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的“日期”工作正常,但Java(没有TZ设置)会感到困惑。

3 个答案:

答案 0 :(得分:2)

按照吉尔斯在https://unix.stackexchange.com/questions/452559/what-is-etc-timezone-used-for中的回答,由于历史原因,Java读取/etc/timezone而不是/etc/localtime。可以在该帖子中找到进一步的解释。

答案 1 :(得分:1)

我和你有同样的问题(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

答案 2 :(得分:0)

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