之前在 AWS EC2 上部署 docker Java 应用时 , 发现 Java log4j 的打印日志时间和宿主时间不一致 . 应用和宿主均是 CST 时间, 而容器还是 UTC 时区. 网上翻阅了不少解决办法, 现记录于此 .

容器与宿主时间不一致

通过 date 命令查看时间

查看主机时间

1
date

查看容器时间

1
docker exec -it {容器id} date

可以发现 , 时间差了 8 个小时.

  • CST (China Shanghai Time , 东八区时间)
  • UTC (Coordinated Universal Time , 标准时间)

解决方案

共享主机的 localtime

创建容器的时候指定启动参数 , 挂载 localtime 文件到容器内 (只读) , 保证两者所采用的时区是一致的.

1
docker run --name <name> -v /etc/localtime:/etc/localtime:ro

复制主机的 localtime

1
docker cp /etc/localtime:【容器ID或者NAME】/etc/localtime

创建自定义的 dockerfile

创建 dockerfile 文件 , 自定义该镜像的时间格式及时区

1
2
3
4
5
6
FROM redis
FROM tomcat
ENV CATALINA_HOME /usr/local/tomcat
#设置时区
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo 'Asia/Shanghai' >/etc/timezone \

生成镜像即可

Issue

!!! 然而发现如此操作后 , Java log4j 的时间仍是 UTC 时间 . 网上太多回复止于上面的方法 .

log4j 主要是使用 springboot 内嵌的 tomcat 的时间 , 因此需要在制作镜像时进行指定 -Duser.timezone=GMT+8

1
2
3
4
5
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","-Duser.timezone=GMT+8","/app.jar","--spring.profiles.active=dev"]

Ok , 搞定 .

参考链接