关于Java:Docker容器中的OpenJDK 1.8.0的时区与/ etc / timezone的时区不同,并且与主机的时区不同

OpenJDK 1.8.0 in Docker container has different timezone than /etc/timezone and from the host

我有一个运行Docker容器的Linux盒子,该容器正在运行TomEE,并运行我构建的WAR。

在基本的Linux框上,我得到的"日期"值是" PST 2017年1月20日10:37:27"。未设置TZ环境变量。

当我运行以下课程时:

1
2
3
4
5
6
7
8
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()) +"]");
        }
}

我明白了:

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

这很好。

在运行在该容器上的Docker容器中,其中我将" -v / etc / localtime:/ etc / localtime"作为卷映射之一,显然,我具有相同的/ etc / localtime文件。未设置TZ环境变量。当我在容器中运行"日期"时,我得到的时间值与基本主机中的时区(PST)相同。

然后我编译并运行与上述相同的Java类,并得到以下信息:

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

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

然后我在容器上重新运行该类,并得到以下信息:

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

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

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

我不得不手动将容器上的TZ设置为主机的TZ值,这使其正常工作。我真的不愿意这样做。对我来说,这似乎是一种hack。

更新:

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

Because the timezone identifier is extracted from the symlink target
name of /etc/localtime, this file may not be a normal file or hardlink.

所以,这可能是我的问题的一部分。仍然很好奇外壳中的"日期"工作正常,但是Java(没有TZ设置)感到困惑。


我遇到了与您相同的问题(CentOS,Docker,OpenJDK)。我们通过以下方式解决了它:

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

如果没有/ etc / timezone文件(例如,在CentOS上),则可以在主机上执行以下操作:

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

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

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

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


可能会转储环境(env命令),LC _ *(通常为LC_ALL)会影响环境。