Bazel构建Go二进制Docker中Delve调试报错排查求助
could not launch process: fork/exec /go/src/my_bin_svc: function not implemented 系统与构建工具信息
- 宿主系统:Mac OS M1
- 构建工具:Bazel,目标平台linux-amd64
- 运行环境:Docker 20.10.17
构建与配置文件
Bazel构建命令
bazelisk build -c dbg --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64 //...
目标服务BUILD文件
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") go_library( name = "cmd_lib", srcs = ["main.go"], importpath = "github.com/xxxxxxxxxx/src/go-grpc-order-svc/cmd", visibility = ["//visibility:private"], deps = [ "//pkg/event", "//pkg/schema", "//proto/order", "//src/go-grpc-order-svc/pkg/client", "//src/go-grpc-order-svc/pkg/config", "//src/go-grpc-order-svc/pkg/db", "//src/go-grpc-order-svc/pkg/repository", "//src/go-grpc-order-svc/pkg/service", "@com_github_tinrab_retry//:retry", "@org_golang_google_grpc//:go_default_library", ], ) go_binary( name = "cmd", embed = [":cmd_lib"], goarch = "amd64", goos = "linux", visibility = ["//visibility:public"], )
Dockerfile
FROM golang:1.18-bullseye ENV GOOS="linux" ENV APP_HOME /go/src RUN mkdir -p "$APP_HOME" WORKDIR "$APP_HOME" EXPOSE 50053 EXPOSE 8080 EXPOSE 4000 RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go install -gcflags="all=-N -l" -ldflags "-s -w -extldflags '-static'" github.com/go-delve/delve/cmd/dlv@latest ENV GO111MODULE=off ENTRYPOINT ["/go/bin/linux_amd64/dlv", "--listen=:4000", "--headless=true", "--api-version=2", "--log=true", "exec", "/go/src/my_bin_svc"]
docker-compose配置片段
my-bin-svc: build: dockerfile: src/go-grpc-order-svc/Dockerfile.debug context: . volumes: #- ./bazel-bin/src/go-grpc-order-svc/cmd/cmd_/cmd:/go/src/order_svc - ./bazel-out/darwin_arm64-dbg/bin/src/go-grpc-order-svc/cmd/cmd_/cmd:/go/src/my_bin_svc ports: - "50053:50053" networks: - backend links: - order-db depends_on: - order-db
问题详情
Bazel生成两个版本的二进制文件:
- bazel-out/darwin_arm64-dbg:带调试符号的Darwin ARM64二进制,单独运行正常,但用Delve调试时报错
- bazel-bin:Linux AMD64二进制,单独运行正常,Delve调试同样报错
已尝试在docker-compose中添加platform: linux/amd64,问题仍未解决。
解决思路
1. 确保二进制与Delve架构完全匹配
当前挂载的darwin_arm64-dbg二进制是Mac本地ARM架构产物,Docker容器是linux/amd64环境,即使qemu能模拟运行,Delve调试也要求架构严格一致,否则会触发function not implemented错误。
修正方案:
修改docker-compose的volume路径,指向Bazel生成的linux-amd64调试二进制,正确路径应为bazel-out/linux_amd64-dbg/bin/src/go-grpc-order-svc/cmd/cmd_/cmd(根据实际生成路径调整),替换掉darwin架构的版本。
2. 调整Delve编译参数
当前Dockerfile中用CGO_ENABLED=0静态编译Delve,可能存在兼容性问题。尝试关闭静态编译并开启CGO:
修改Dockerfile中的Delve安装命令:
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go install -gcflags="all=-N -l" github.com/go-delve/delve/cmd/dlv@latest
(移除-ldflags "-s -w -extldflags '-static'"参数)
3. 验证二进制调试信息完整性
确认Bazel的-c dbg参数生效,生成的二进制包含完整调试符号。在容器内执行file /go/src/my_bin_svc,输出应显示为debug build且架构为x86_64。
4. 赋予容器调试所需权限
Delve调试需要特定系统权限,在docker-compose中添加以下配置:
my-bin-svc: # ... 其他原有配置 cap_add: - SYS_PTRACE security_opt: - seccomp:unconfined
5. 尝试用Delve的debug命令替代exec
如果直接调试二进制仍有问题,可让Delve直接调试源码(需挂载本地源码到容器),修改Dockerfile的ENTRYPOINT:
ENTRYPOINT ["/go/bin/dlv", "--listen=:4000", "--headless=true", "--api-version=2", "--log=true", "debug", "github.com/xxxxxxxxxx/src/go-grpc-order-svc/cmd"]
同时在docker-compose中添加源码挂载:
volumes: - ./src/go-grpc-order-svc:/go/src/github.com/xxxxxxxxxx/src/go-grpc-order-svc
内容的提问来源于stack exchange,提问作者Dmitry K

