英文:
Compile Static Go Binary with Debug Symbols in Separate File?
问题
我记不清我在哪里看到的了,我想可能是在Datadog、NewRelic或者CloudFlare上?但我记得有人提到使用Golang时,在生产环境中运行发布的二进制文件,并在Docker容器中还包含一个单独的文件,其中包含调试符号,以防发生崩溃,以便能够查看发生了什么。
背景
我正在使用以下Dockerfile构建和运行:
# 在一个镜像中进行所有的Docker构建
FROM golang:latest as build
WORKDIR /usr/src/api
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# 使用相关的标志构建应用程序,使其完全自包含以用于scratch容器
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags "-s" -a -installsuffix cgo -o app
# 然后将构建的二进制文件复制到一个空镜像中
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 /
# 默认在开发环境中运行
ENV ENV=dev
EXPOSE 8080
ENTRYPOINT ["/bin/bash"]
如果我不使用上面的标志,在alpine
和scratch
基础镜像中,二进制文件将无法执行:
standard_init_linux.go:219: exec user process caused: no such file or directory
在ubuntu:latest
中运行就可以正常工作,所以上述编译标志似乎修复了alpine
和scratch
的问题。
问题
在这种环境下,是否可能让go build
将调试符号输出到一个单独的文件中,与我的静态二进制文件一起存在于Docker镜像中?
英文:
I can't remember where I saw it, I thought it was on Datadog or on NewRelic or maybe CloudFlare? but I remember someone mentioning that with Golang, they run release binaries in production (of course), and within their Docker containers, they also include a separate file containing debug symbols in case a crash occurs so as to be able to see what happened.
Background
I'm building and running in Docker with a Dockerfile like this:
# 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"]
If I don't use the flags above, the binary will fail to execute in alpine
and scratch
base images:
standard_init_linux.go:219: exec user process caused: no such file or directory
Running this in ubuntu:latest
just works, so the above compile flags seem to fix the issue for alpine
and scratch
.
Question
With this environment in mind, is it possible to have go build
emit debug symbols into a separate file to live alongside my static binary in the Docker image?
答案1
得分: 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
这样应该可以实现您所要求的行为(例如,一个小的生产二进制文件,但也有一个带有符号的备份二进制文件,用于在生产环境中调试问题)。
英文:
You don't need to use " -a -installsuffix cgo" flags when building with CGO_ENABLED=0 -- just setting the environment variable will do the trick.
You are building with "-ldflags -s", which is going to strip out all debug symbols and ELF symbol table information. Instead of doing that, do a regular build, archive that executable (in case you need the symbols later) and then remove symbols using strip. E.g.
$ 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
That should give you the behavior you're asking for (e.g. a small production binary, but also a backup binary with symbols for debugging problems in production).
答案2
得分: 2
使用go tool compile
命令,并使用-E
标志来进行调试符号导出。这是你需要的吗?
$ go tool compile -E *.go
输入以下命令获取更多关于如何使用以及可用选项的帮助:
go tool compile
参考链接:
英文:
Use go tool compile
using -E
flag to Debug symbol export
. Is that what you need?
$ go tool compile -E *.go
Type:
go tool compile
for more help regarding how to use it and what are the options available.
Reference:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论