作者: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一类的时区
而且本地测试,发现这个方法也没有出现报错。
而在容器中,就是会产生报错。
这里我们就需要查看"$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
两种办法均可以,个人推荐第一种。
重新构建后重新运行容器,即可发现已经不存在此问题