容器化Go应用--基础镜像的未知时区问题

栏目: IT技术 · 发布时间: 5年前

内容简介:用使用如果你的应用程序在初始化函数

Go 开发的应用程序的一个优势在于,可以从"零"开始构建应用的 Docker 镜像,镜像中仅需要包含 Go 应用程序编译后的二进制文件,不需要额外安装其他执行环境。这样一来 Go 应用镜像占用的空间确实很小(通常是几 MB ),而且也会更安全些。常用的 alpine 镜像( alpine 是专门为容器设计的小型 Linux 发行版)中存在一个安全漏洞,该漏洞为大量生产容器留下了空的 root 用户密码,所以如果你的的 Go 应用程序在没有 alpine (或任何其他操作系统)的容器中运行,黑客就不能利用操作系统的漏洞去攻击容器里的应用。

使用 Docker 的多阶段构建,从头开始构建映像非常简单,上一期的文章《 线上 Go 项目的 Docker 镜像应该怎么构建? 》里已经对此进行了详细描述。怎么从 "scratch" 基础镜像,使用多阶段构建制作 Go 应用程序的镜像。今天接着上期的话题继续说一个从零构建的应用镜像的容器时区设置的问题。

如果你的应用程序在初始化函数 init 里有设置时区的操作,那么在启动应用容器时会遇到下面这个运行时 panic

unknown time zone Asia/Shanghai
复制代码

如果你在应用程序里不显示地设置时区,应用容器确实是能正常启动的,只不过这样 time 包里的函数统一用的是 UTC 时区,等你发现问题时再在程序里去显示设置时区仍然会遇到上面的运行时错误。

下面我们来做个试验,看看上面说的问题的现象。

首先写一个简单的 Go 应用程序

package main

import (
   "fmt"
   "time"
)

func main() {
   // 输出当前的时区
   fmt.Print("Local time zone ")
   fmt.Println(time.Now().Zone())
   fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
}
复制代码

然后写一个用来构建应用镜像的 Dockerfile ,使用的就是之前介绍的多阶段构建。

FROM golang:alpine as build
RUN apk --no-cache add tzdata
WORKDIR /app
ADD . /app
RUN CGO_ENABLED=0 GOOS=linux go build -o myapp

FROM scratch as final

COPY --from=build /app/myapp .
ENV TZ=Asia/Shanghai

CMD ["/myapp"]
复制代码

Dockerfile 里,我们用 ENV 指令设置了 TZ 这个环境变量。 Go 运行时会查找 TZ 这个环境变量来设置自己的时区,上面我们把 TZ 设置成了 Asia/Shanghai ,接下来我们看看在容器里应用是不是能如期运行,输出正确的时区和时间。

➜  docker build -t go_timezone .


➜  docker run --rm go_timezone
Local time zone UTC 0
2020-07-17 04:47:37

复制代码

根据运行结果发现时区的设置并没生效。

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",
}
复制代码

于是我就进到刚才镜像的容器里看了看,上面列的几个目录都没有找到。到这里算是定位到问题了, scratch 镜像里并不包含这些时区文件。那么解决办法就是从 build 阶段的镜像里拷贝时区文件到最终的应用镜像。

FROM golang:alpine as build
RUN apk --no-cache add tzdata
WORKDIR /app
ADD . /app
RUN CGO_ENABLED=0 GOOS=linux go build -o myapp

FROM scratch as final

COPY --from=build /app/myapp .
### 下面这行是新加的
COPY --from=build /usr/share/zoneinfo /usr/share/zoneinfo
ENV TZ=Asia/Shanghai

CMD ["/myapp"]
复制代码

重新构建镜像、运行容器后就能发现时区设置已经正常了,Go运行时按照环境变量 TZ 里指定的时区打印了当前时间。

➜  docker image rm go_timezone
➜  docker run --rm go_timezone
Local time zone CST 28800
2020-07-17 13:12:18.206 CST

复制代码
容器化Go应用--基础镜像的未知时区问题

容器化Go应用--基础镜像的未知时区问题


以上所述就是小编给大家介绍的《容器化Go应用--基础镜像的未知时区问题》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

程序设计语言

程序设计语言

斯科特 / 裘宗燕 / 电子工业出版社 / 2005-1 / 88.00元

这是一本很有特色的教材,其核心是讨论程序设计语言的工作原理和技术。本书融合了传统的程序设计语言教科书和编译教科书的有关知识,并增加了一些有关汇编层体系结构的材料,以满足没学过计算机组织的学生们的需要。书中通过各种语言的例子,阐释了程序设计语言的重要基础概念,讨论了各种概念之间的关系,解释了语言中许多结构的形成和发展过程,以及它们演化为今天这种形式的根源。书中还详细讨论了编译器的工作方式和工作过程,......一起来看看 《程序设计语言》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具