如何编译包含调试符号的静态Go二进制文件到单独的文件中?

5
我无法回忆起我在哪里看到的,我记得有人提到使用Golang时,在生产环境中运行发布二进制文件,并在Docker容器中包含一个单独的文件,其中包含调试符号,以便在发生崩溃时能够查看发生了什么事情。可能是在Datadog、NewRelic或CloudFlare上看到的。
背景: 我正在构建并在Docker中运行,使用类似这样的Dockerfile:
# do all of our docker building in one image
FROM golang:latest as build

WORKDIR /usr/src/api

COPY go.mod go.sum ./
RUN go mod download

COPY . .

# build the application with relevant flags to make it completely self-contained for a scratch container
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags "-s" -a -installsuffix cgo -o app

# and then copy the built binary to an empty image
FROM ubuntu:latest

COPY --from=build /usr/src/api/app /
COPY --from=build /usr/src/api/config.defaults.json /config.json
COPY --from=build /usr/src/api/logo.png /

# default to running in a dev environment
ENV ENV=dev

EXPOSE 8080

ENTRYPOINT ["/bin/bash"]

如果我不使用上述标志,二进制文件将无法在 alpinescratch 基础镜像中执行:

standard_init_linux.go:219: exec user process caused: no such file or directory

在使用ubuntu:latest上运行此命令可以正常工作,因此似乎上述编译标志可以解决alpinescratch的问题。

问题

考虑到这个环境,是否可能让go build将调试符号发射到一个单独的文件中,与我的静态二进制文件一起存在于Docker镜像中?

2个回答

3

在使用CGO_ENABLED=0时,您不需要使用“-a -installsuffix cgo”标志进行构建——只需设置环境变量即可。

您正在使用“-ldflags -s”进行构建,这将剥离所有调试符号和ELF符号表信息。而不是这样做,可以进行常规构建,存档可执行文件(以防以后需要符号),然后使用strip删除符号。例如:

 $ CGO_ENABLED=0 GOOS=linux go build -o app.withsymbols
 $ cp app.withsymbols /my/archive/for/debugging/production/issues
 $ strip app.withsymbols -o app.stripped
 $ cp app.stripped /production/bin

这将给您所需的行为(例如,一个小的生产二进制文件,但也是备用带符号的二进制文件,以便在生产环境中调试问题)。


2
使用-E标志的go tool compile来进行Debug symbol export。这是你需要的吗?
$ go tool compile -E *.go

类型:

go tool compile

欲了解更多关于如何使用和可用选项的帮助,请参考:

参考资料:

  1. https://golang.org/cmd/compile/

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