Vscode debug GoLang micro-services in Docker

UULU · · 1402 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

English

查一般的 bug,我更习惯直接加打印,能快速定位问题,远比断点调试方便的多。但遇到一些复杂、或是涉及第三方类库时,却不得不需要添加断点逐步跟踪逻辑。

使用 golang 开发的微服务,全部是直接运行在 docker 容器里的,想要调试并不是一件简单的事情,这时候我们就需要 Remote Debug (远程调试)

  • vscode - 代码编辑器
  • ms-vscode.go - vscode 支持 Go 语言的插件
  • delve - Golang 调试工具,支持远程调试
  • Makefile - 封装指令的合集
  • alpine - 迷你 Docker 系统镜像,只有 5MB

启动容器

通过MakefileDockerfile编译镜像和运行 Docker 容器,我的方式是在本地(MacOS)上编译好 Linux 的可执行文件,拷贝到用 alpine 小镜像创建的容器里。也可以选择用 golang 镜像,拷贝源码进去。

  1. 配置 Makefile
  • 注意在编译应用程序时需要,通过添加 -gcflags "all=-N -l" 生成支持 Debug 的包
  • 运行容器时需要通过参数 -security-opt="seccomp=unconfined" --cap-add=SYS_PTRACE 关闭容器的安全限制
  • 运行时需要把 dlv 监听的端口暴露出来 -p 20000:20000,以便 vscode 调试程序去连接
NAME := account
IMAGE := $(NAME)-service

# 编译镜像
build-debug:
    # 清理废弃的image (按需开启)
    docker image prune -f

    # 编译Linux版 dlv可执行文件
    GOOS=linux GOARCH=amd64 go build github.com/go-delve/delve/cmd/dlv

    # 编译Linux版 应用可执行文件
    GOOS=linux GOARCH=amd64 go build -gcflags "all=-N -l"

    # 指定Dockerfile 生成镜像
    docker build -f Dockerfile.debug -t $(IMAGE) .

    # 清理掉生成的可执行文件
    rm -f $(NAME) dlv

# 运行容器
run-debug:
    # my-docker-network 是我的Docker network,所有的微服务都在这个网络里,可以直接互连
    docker run --rm --name $(IMAGE) \
    --network my-docker-network \
    --security-opt="seccomp=unconfined" --cap-add=SYS_PTRACE \
    -p 20000:20000 \
    $(IMAGE)


debug: build-debug run-debug
  1. 配置 Dockerfile.debug

容器启动入口为 ./dlv --listen=:20000 --headless=true --api-version=2 --log=true exec ./account

  • ./代表 WORKDIR 的/app目录,dlv、account 可执行文件我们通过 Dockerfile 都已经添加到这个目录里了
  • --listen=:20000 dlv 服务绑定的端口
  • --headless=true 调试服务器,无 ui 模式
  • --api-version=2 服务提供的 API 版本
  • --log=true 开启日志,否则只能看到应用日志,没有 dlv 自身的日志
  • exec ./account 准备执行的程序,这个程序必须支持 Debug

exec对应的还有另外一个指令: debug,直接调试源码可以用

FROM alpine:3.9

# 应用程序需要这个组件来支持请求HTTPS的网址
RUN apk add ca-certificates

RUN mkdir /app
WORKDIR /app

ADD dlv account config.yml ./

ENTRYPOINT ["./dlv", "--listen=:20000", "--headless=true", "--api-version=2", "--log=true", "exec", "./account"]
  1. 运行容器

会发现没有应用启动日志,是因为微服务在此时还未被拉起,只是关联好了

$ make debug
...
2019-05-08T13:03:23Z info layer=debugger launching process with args: [./account]
API server listening at: [::]:20000

Vscode 配置及断点调试

  1. 配置启动文件
  • mode remote 开启远程模式

  • hostport 配置成 dlv 暴露出的服务器地址

  • program 配置成本地对应的源码 main 文件

  • launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Remote Debug",
      "type": "go",
      "request": "launch",
      "mode": "remote",
      "remotePath": "",
      "port": 10001,
      "host": "127.0.0.1",
      "program": "${workspaceRoot}/cmd/account/main.go",
      "showLog": true,
      "env": {},
      "args": []
    }
  ]
}
  1. 点击开始调试,应用才开始运行,所以可以看出是 vscode 客户端通知 dlv 服务器启动应用的
  2. 这时候我们在 vscode 里创建一个断点,服务器会出现对应的日志。
2019-05-08T13:06:03Z debug layer=debugger halting
2019-05-08T13:06:03Z info layer=debugger created breakpoint: ...
2019-05-08T13:06:03Z debug layer=debugger continuing
  1. 接下来就和在本地调试程序是一样的了。

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:UULU

查看原文:Vscode debug GoLang micro-services in Docker

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1402 次点击  
加入收藏 微博
3 回复  |  直到 2019-05-09 15:31:42
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传