作者:admin,发布日期:2020-12-27
阅读:2085;评论:0

背景

今天在用docker跑翼龙构建好的wings docker镜像时候,发现只能给程序设置UTC时区,一旦设置Asia/Shanghai,程序就报错could not load time location: unknown time zone Asia/Shanghai,而程序又要依赖这个时区,研究了一下午,没有进展。晚上突然想到可能是容器环境的原因,于是百度查找该报错,确实找到相同问题。

探究

经过检查,问题出现在如下代码中:

_, err := time.LoadLocation(a)

仔细查看文档,文档中也表明支持Asia/Shanghai一类的时区

Snipaste_2020-12-27_23-48-53.png

而且本地测试,发现这个方法也没有出现报错。

Snipaste_2020-12-27_23-49-50.png

而在容器中,就是会产生报错。

这里我们就需要查看"$GOROOT/src/time/zoneinfo.unix"

在Linux系统下Go运行时会从多个来源读取时区信息,在$GOROOT/src/time/zoneinfo.unix文件里能够找到Go运行时是从哪些地方读取时区信息的。

// Many systems use /usr/share/zoneinfo, Solaris 2 has// /usr/share/lib/zoneinfo, IRIX 6 has /usr/lib/locale/TZ.var zoneSources = []string{
   "/usr/share/zoneinfo/",
   "/usr/share/lib/zoneinfo/",
   "/usr/lib/locale/TZ/",
   runtime.GOROOT() + "/lib/time/zoneinfo.zip",}

看到这段代码,几乎可以判定因为我们的容器不带这些文件,所以才导致的无法加载此类时区。

进入容器,我们可以进入/usr/share/zoneinfo目录,可以发现是进入不了的。

解决方法

经过百度查询,我们可以知道zoneinfo的文件来自tzdata,所以我们可以在打包的时候安装这个包。

在Dockerfile里面加入以下代码,这样zoneinfo就会被安装进系统

RUN  apk add tzdata

或者如果builder容器中存在这些文件的话,我们可以通过命令直接从上一个构建容器中拷贝进来

COPY --from=build /usr/share/zoneinfo /usr/share/zoneinfo

两种办法均可以,个人推荐第一种

重新构建后重新运行容器,即可发现已经不存在此问题