使用 Docker 部署 Java 程序时发现时区有问题,这里记录下这期间折腾的记录。
背景
基础镜像为 openjdk:8-jre-alpine
,复制打包后生成的 jar 文件进去运行程序。
这个镜像默认的配置如下
1 2 3 4 5 6
| $ docker run -it / Tue Dec 11 01:41:09 UTC 2018 / TZif2UTCTZif2UTC UTC0
|
测试
以下是用来测试的 Dockerfile
1 2 3 4 5 6 7 8
| FROM openjdk:8-jre-alpine
COPY ./target/tz-1.0-SNAPSHOT.jar main.jar CMD /usr/bin/java -jar main.jar
|
测试用的 Java 程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.lycheng.tz;
import java.time.Instant; import java.util.Date; import java.util.TimeZone;
public class Main {
public static void main(String[] args) { Instant instant = Instant.now(); System.out.println(instant);
TimeZone tz = TimeZone.getDefault(); System.out.println(tz.getDisplayName()); Date date = new Date(); System.out.println(date); } }
|
上述两行注释都是可用的
1 2 3 4 5
| > docker run --rm -it $(docker build -q .)
2018-12-11T03:39:17.927Z China Standard Time Tue Dec 11 11:39:18 CST 2018
|
以上就是 alpine issue 中提及的方法,原因是 alpine 这个基础镜像是很精简的,原镜像不包含时区信息,需要额外安装。
此外,你也可以在代码中设置时区
1
| TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
|
在搜索的时候也发现另外的好玩的方法,就是使用宿主机本身的 /etc/localtime
1
| docker run -v /etc/localtime:/etc/localtime:ro -v /etc/timezone:/etc/timezone:ro -it --rm openjdk:8-jre-alpine /bin/sh
|
这样子能减少 image 的大小,又不需要另外设置时区信息。而 ubuntu 的镜像除了设置环境变量 TZ 外还需要别的配置才行,详见 这里
参考