使用Docker镜像构建Golang二进制文件

3

我有一个Go应用程序,已编译成二进制文件,并且作为Docker镜像进行分发。

目前,我使用的基础映像是ubuntu,但这会导致一个问题,即如果用户尝试使用UTC或本地时区之外的时区,则会出现错误,提示:

pod error: panic: open /usr/local/go/lib/time/zoneinfo.zip: no such file or directory

这个错误是因为在Go语言中的LoadLocation包需要该文件引起的。
我可以想到两种方法来解决这个问题:
  1. 继续使用ubuntu基础镜像,但在我的Dockerfile文件中添加命令:RUN apt-get install -y tzdata

  2. 使用Golang的基础镜像之一,例如golang:1.7.5-alpine

哪种方法是推荐的? 我不确定是否应该使用Golang图像,因为这是预构建二进制文件运行的容器。 我的理解是Golang图像适用于首先构建二进制文件。

如果您需要 tzdata 包,则需要安装该包。您正在使用哪个镜像来构建二进制文件? - JimB
我目前没有在容器内构建。我打算使用golang:1.7.5-alpine容器进行构建来解决这个问题。 - Ayush
1
如果你不是使用alpine构建程序,那么你需要确保你正在构建一个静态二进制文件,如果你打算在alpine上发布。无论如何,如果你的程序中使用了zoneinfo,你最终的容器中都需要包含它。 - JimB
@JimB 我目前正在构建一个针对我的当前运行时容器的静态二进制文件。关于zoneinfo,我正在尝试找出在我的最终容器中拥有它的最佳方法 - 我应该在我的ubuntu容器中安装tzdata软件包,还是使用其中一个golang容器。 - Ayush
这完全取决于您。您可以查看相关的Dockerfiles,看看哪个比另一个更适合您的需求。这里没有“正确”的答案。 - JimB
4个回答

3

我更喜欢使用多阶段构建。在第一阶段,您可以使用特殊的 Golang 构建容器来安装所有依赖项并构建应用程序。在第二阶段,将二进制文件复制到空的 alpine 容器中。这样可以同时拥有所有所需的工具和最小的 Docker 镜像(在我的情况下是 6MB,而不是 280MB)。

Dockerfile 的示例:

# build stage
FROM golang:1.8
ADD . /src
RUN set -x && \
    cd /src && \
    go get -t -v github.com/lisitsky/go-site-search-string && \
    CGO_ENABLED=0 GOOS=linux go build -a -o goapp

# final stage
FROM alpine
WORKDIR /app
COPY --from=0 /src/goapp /app/
ENTRYPOINT /goapp
EXPOSE 8080

1
使用这种方法,您的最终运行时容器将不会在/usr/local/go/lib/time/路径下包含时间数据。 - Ayush
@xbonez 当然,如果您需要一些未编译成二进制文件的数据文件,您可以使用ADD命令将它们添加进去。这样,您就可以获得最小的镜像 - 只有您需要的东西。 - Eugene Lisitsky

2
由于并非所有操作系统都安装了本地化的时区,因此我所做的就是使其正常工作:
ADD https://github.com/golang/go/raw/master/lib/time/zoneinfo.zip /usr/local/go/lib/time/zoneinfo.zip

添加时区的多步骤Docker镜像的完整示例在这里

1
你可以使用系统的 tzdata。或者你可以将 $GOROOT/lib/time/zoneinfo.zip 复制到你的镜像中,这是一个修剪过的版本系统时区数据的文件。

1

这更像是一次投票,但在这种情况下,我们(我公司的技术组)使用apt-get。它使我们完全控制图像层次结构,但这是基于您可能会有未来的图片。


谢谢。我将其标记为已接受,因为这是我最终采用的方法。 - Ayush

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接