【问题标题】:How to create a binary that contains zoneinfo.zip如何创建包含 zoneinfo.zip 的二进制文件
【发布时间】:2019-02-28 13:21:18
【问题描述】:

我正在使用 Docker 创建一个容器应用程序,然后将其部署到 kubernetes engine,但是当应用程序初始化时,我收到此错误:

err: open C:\Go/lib/time/zoneinfo.zip: no such file or directory

【问题讨论】:

    标签: go kubernetes containers google-kubernetes-engine


    【解决方案1】:

    您可以考虑构建您的 Go 应用程序 with Go 1.15(2020 年 8 月,两年后)

    新的嵌入式 tzdata 包

    Go 1.15 包含一个新包time/tzdata,它允许将时区数据库嵌入到程序中。

    • 导入此包(如import _ "time/tzdata")允许程序查找时区信息,即使本地系统上没有时区数据库。
    • 您还可以通过使用-tags timetzdata 构建来嵌入时区数据库。

    任何一种方法都会使程序的大小增加大约 800 KB。

    这样,一旦作为 Docker 映像部署到 Kubernetes 引擎,它就不必尝试加载任何时区信息,因为所述信息已嵌入其程序中。

    警告commenteddolmen

    此解决方案的缺点是时区信息版本与您用于构建的 Go 版本相关联

    如果您继续为您的项目使用固定版本的 Go,您将保留该版本的时区。

    能够独立于 Go 版本更新时区信息(每次重建 Docker 映像以进行部署时更新)可能是更好的选择。

    作为插图,请参阅 dolmen 的answer

    【讨论】:

    • 这个解决方案的缺点是时区信息版本链接到你用于构建的 Go 版本。如果您继续为您的项目使用固定版本的 Go,您将保留该版本的时区。能够独立于 Go 版本更新时区信息(每次重建 Docker 映像以进行部署时更新)可能是更好的选择。
    • @dolmen 感谢您的反馈:很好。我已编辑答案以包含您的评论以提高知名度,并为您自己的答案投票。
    【解决方案2】:

    当使用 Go 的 time 包,特别是 LoadLocation 方法时,它会在各个位置查找time zone database 信息。这在 https://golang.org/src/time/zoneinfo.go 源代码中 LoadLocation 的 cmets 中进行了解释。具体来说,它会在这些地方查看:

    1. 由 ZONEINFO 环境变量指定的位置
    2. 在 Unix 操作系统上保存时区数据库文件的已知位置
    3. $GOROOT 中的 zoneinfo.zip 文件

    当您在 Windows 机器上编程时,Go 很可能默认使用第三个选项。但是,当您使用二进制文件时,没有 $GOROOT,因此它在您的容器中不起作用。在大多数版本的 Linux 上,第二个选项可以正常工作,因为它们具有必要的时区数据库文件。但是,我强烈怀疑您引用的优化容器没有。这为您留下了选项 1,它基本上包括将您自己的时区数据库文件放在容器上,然后使用 ZONEINFO 环境变量引用它们的位置。这既是一种痛苦,我还发现当您请求一个不存在的时区文件时,它会默默地失败。

    在我自己解决这个问题时,我最终创建了一个使用 LoadLocationFromTZData 方法的包,并尝试简化提供和使用您自己的时区数据库副本的过程。你可以在这里看到我自己的堆栈溢出问题:Detect if ZONEINFO fails in Go。您可以在此处查看我的时区包的存储库:https://github.com/slotheroo/knozone

    【讨论】:

    • 是的,我确实做到了,对我来说幸运的是,我只需要一个时区,即我的时区(至少现在是这样),希望尽快修复,357B 是 zoneinfo 的大小.zip,将其添加到二进制文件不会伤害任何人
    【解决方案3】:

    使用 Dockerfile 构建 zoneinfo.zip 以及构建您的应用程序。

    FROM golang:1.17.1-alpine3.14 AS builder
    
    ...
    WORKDIR /src
    ...
    RUN GOOS=linux GO111MODULE=on go build -trimpath -o my_app 
    ....
    
    FROM alpine:latest as alpine
    
    # Update timezone info and TLS certificates
    RUN apk --no-cache add tzdata zip ca-certificates
    WORKDIR /usr/share/zoneinfo
    # -0 means no compression.  Needed because go's
    # tz loader doesn't handle compressed data.
    RUN zip -r -0 /zoneinfo.zip .
    
    # Final image.
    FROM scratch
    
    # Timezone data
    ENV ZONEINFO /zoneinfo.zip
    COPY --from=alpine /zoneinfo.zip /
    # TLS certificates
    COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
    
    COPY --from=builder /src/my_app
    

    您可能还对Google Distroless base Docker images 感兴趣。

    【讨论】:

      【解决方案4】:

      我一周前遇到了同样的问题,最后在 Dockerfile 上解决了这个问题。

      首先,您需要找到zoneinfo.zip 文件。例如,在通过 brew 安装 Go 的 MacOS 上可能会变得很棘手。

      tztest$ go env GOROOT
      /usr/local/Cellar/go/1.12.7/libexec
      tztest$ ls -l /usr/local/Cellar/go/1.12.7/libexec/lib/time/zoneinfo.zip
      -rwxr-xr-x  1 mau  staff  365447 Jul  8 16:29 /usr/local/Cellar/go/1.12.7/libexec/lib/time/zoneinfo.zip
      

      所以解决方法是复制 zoneinfo.zip 并包含在 Dockerfile 的同一目录中。从那里开始,只需将文件添加到 docker 构建过程并覆盖环境变量

      ADD zoneinfo.zip /zoneinfo.zip
      ENV ZONEINFO /zoneinfo.zip
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-02
        • 1970-01-01
        • 2010-12-07
        • 1970-01-01
        • 1970-01-01
        • 2021-10-05
        • 1970-01-01
        • 2017-03-16
        相关资源
        最近更新 更多