在Docker中调试Go程序

我们已经构建一个用于编译Go程序的,如果我们使用Mac和Windows开发go,又该如在docker中调试我们程序。这其中用到了一个调试工具delve的远程调试功能。

认识Delve

项目地址:https://github.com/go-delve/delve

Devle是一个非常棒的golang 调试工具,支持多种调试方式,直接运行调试,或者attach到一个正在运行中的Go程序,进行调试。线上Go服务出现问题时,Devle是必不可少的在线调试工具,如果使用docker,也可以把Devle打进docker镜像里,从而调试代码。

创建调试容器

Dockerfile内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 最新版本构建容器
FROM golang:latest
MAINTAINER cheuk
# 创建构建目录
RUN mkdir /godebuger
# 工作目录
WORKDIR /godebuger
# delve的调试端口
EXPOSE 2345
# 环境变量配置
ENV GOPATH $GOPATH:/godebuger
ENV GO111MODULE on
# 开下梯子
ENV GOPROXY "https://goproxy.cn"
RUN go get -u github.com/go-delve/delve/cmd/dlv
# 磁盘映射package
VOLUME ["/godebuger","/go/src"]

构建容器

1
docker build -t godebuger .

选择一个项目,并映射到进入容器中,$(pwd)就是项目的目录,我习惯进入项目目录执行。

1
docker run --rm -it -v $GOPATH/src:/go/src -v $(pwd):$(pwd) godebuger

注意:这里$(pwd):$(pwd)是将项目完整目录映射到容器,不然在IDE下无法进行打断点调试。

如果我们还使用GOPATH模式编译程序那么

1
export GO111MODULE=off

进入到项目目录编译,开始调试程序

1
go build -gcflags "all=-N -l"
1
dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec ./godebuger

这里的godebuger是项目编译后的程序名称。

这里每一步操作都很麻烦,我们写个脚本放到$GOPATH/bin。如果已经使用go mod 模式则需要去掉-e GO111MODULE=off

1
2
3
4
5
6
7
#!/bin/bash
docker run --rm -it \
-v $GOPATH/src:/go/src \
-v $(pwd):$(pwd) \
-e GO111MODULE=off \
-p 2345:2345 \
godebuger /bin/sh -c 'cd '"$(pwd)"' && go build -gcflags "all=-N -l" -o godebuger && dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec ./godebuger'

在项目目录执行

1
2
~ godebuger
API server listening at: [::]:2345

即可开启调试。如果是*nix系统,添加下执行权限。

1
chmod +x $GOPATH/bin/godebuger

IDE配置

使用idea为例,点击编辑配置项

添加go远程调试项,修改名称点OK创建

godebuger-idea-add-remote

点击如图所示的按钮,即可正常调试Go程序

godebuger-start-debug