解决.net core3.1部署到Linux CentOS docker时区问题

解决.net core3.1部署到Linux CentOS docker时区问题

311发表于2020-06-02

最近遇到一个“.net core3.1部署到Linux CentOS docker时区“问题,总是不对,始终晚8个小时,程序取到的是UTC时间而不是我想要的东8北京时间。

from clipboard

一、主要技术及框架

1、.Net Core3.1

2、Docker(镜像:mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine)

3、Linux CentOS

4、ElasticSearch,Kibana

5、NLog

二、问题现象

看日志记录的时间戳,始终晚了8个小时,导致通过NLog根据日期没提案生成一个日志索引就有问题,比如6月1号8点之前的日志数据就会落在了5月31号的索引中。如下图:

from clipboard

这个问题虽然通过Kibana选择时间筛选最终可以选择到对应的日志(会自动做一个时区转换),但是始终存在一个问题(8小时的差异),有些日志要到前一天的索引中去查询。这就给我们统计查询带来了不便。

那么我们要怎么修正这个问题呢?

三、分析原因

首先先,我们来看看ES记录的原始信息:

from clipboard

@timestamp记录的是es的date类型,被自动转换成了带时区的字符串:2020-05-31T16:00:00.1209997+00:00

后面加就是相对UTC的时区,加00就表示是UTC时间。

最开始我通过构建docker镜像的时候使用下面命令:

docker cp /usr/share/zoneinfo/Asia/Shanghai lanhusoft-docker:/etc/localtime

其中lanhusoft-docker为容器名。

刚开始以为解决了,最后才知道是暂时解决了,把容器的时间改为了CST,通过date命令查看时间是北京时间了。

但是,过了一段时间重新使用jenkin重新构建,又发现不对了。但是在另外一个程序相同代码,相同构建时间又是正常啊的。(不知道为啥?不知道是不是.net core bug?)

进入容器使用date查看时间又是北京时间,而且宿主机器也是北京时间。奇怪的是.NET Core程序取到的当前时间却是UTC时间。

通过TimeZoneInfo.Local.DisplayName查看找到了原因,返回的是UTC时区时间,而且直接打印DateTime.Now到页面也是跟北京时间晚了8个小时。

看来通过上面的的方法不是完美和根本解决办法,因为alpine镜像先默认是UTC时间。

推荐:

需要指定北京时间,需要安装包tzdata。

四、解决方案

alpine安装包命令是apk add,如果每次构建镜像的时候现安装包tzdata,因为网络原因会很慢,导致影响Jenkin构建的速度。所以我自己写了一个镜像。

aspnet-3.1-alpine-lanhu.dockerfile:

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine
MAINTAINER www.lanhusoft.com <2351310751@qq.com>

#设置alpine时区
ENV TIMEZONE Asia/Shanghai

# Install base packages
RUN apk update && apk add curl bash tree tzdata \
    && cp -r -f /usr/share/zoneinfo/${TIMEZONE} /etc/localtime \
        && echo "${TIMEZONE}" > /etc/timezone \
    && echo -ne "Alpine Linux 3.4 image. (`uname -rsv`)\n" >> /root/.built
# Define bash as default command
CMD ["/bin/bash"]
以上脚本apk除了安装tzdata,还安装了其他基础常用的工具包,curl,bash,tree。

在docker文件aspnet-3.1-alpine-lanhu.dockerfile所在目录运行下面命令构建docker镜像:

docker build -f aspnet-3.1-alpine-lanhu.dockerfile -t aspnet-3.1-alpine-lanhu:latest .

说明:-f镜像脚本文件,-t镜像名称,冒号后面是tag。

最后,在项目的Dockerfile中引用这个新生成的镜像:

FROM aspnet-3.1-alpine-lanhu AS base

ARG app_env=development

WORKDIR /app
EXPOSE 80
COPY . ./

ENV ASPNETCORE_ENVIRONMENT $app_env

ENTRYPOINT ["dotnet", "XX.Web.dll"]
说明:aspnet-3.1-alpine-lanhu就是之前我们自定义的alpine镜像,其中XX.Web.dll是asp.net core的启动dll。

这样每次构建就会很快,基本上10多秒就搞定。

from clipboard


小编蓝狐