【GO 学习笔记】goland 调试 docker 容器中的 go 代码

本贴最后更新于 1601 天前,其中的信息可能已经物是人非

goland 调试 docker 容器中的 go 代码

前言:为什么需要去远程容器中的 go 代码?

最近正在看 Harbor 的源码,由于本人电脑是 windows 无法直接启动进行 debug,后来搭了一个 CentOS 的桌面环境,又发现启动需要很多很多环境参数...而且还有很多其他组件都是运行在 docker 上,使用 linux 系统启动的方案又失败了!后来查了好多资料,找到 delve 这个插件,该插件可以在 docker 容器中,远程调试代码。这里记录下过程(使用的是小 demo 而不是 Harbor)!

一、 下载安装 delve

  1. 进入 GOPATH 路径创建对应目录
mkdir -p $GOPATH/github.com/go-delve
cd $GOPATH/github.com/go-delve
  1. github clone delve 源码
$ git clone https://github.com/go-delve/delve.git
  1. 编译
$ cd $GOPATH/src
$ go install github.com/go-delve/delve/cmd/dlv
  1. 编译完成后 dlv 文件就在 $GOPATH/bin 目录下了,可以以下命令查看版本信息:
$ dlv -v

二、 准备 Demo

  1. 准备一个 demo,文件名为 web.go
package main

import (
	"crypto/md5"
	"fmt"
	"html/template"
	"io"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"
)

func sayHelloName(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()       // 解析参数,默认是不会解析的
	fmt.Println(r.Form) // 这些信息是输出入服务器的打印信息
	fmt.Println("path ", r.URL.Path)
	fmt.Println("scheme ", r.URL.Scheme)
	fmt.Println(r.Form["url_long"])
	for k, v := range r.Form {
		fmt.Println("key:", k)
		fmt.Println("value", strings.Join(v, ""))
	}
	fmt.Fprintf(w, "hello vic")

}

func login(w http.ResponseWriter, r *http.Request) {
	fmt.Println("method ", r.Method)
	if r.Method == "GET" {
		t, _ := template.ParseFiles("login.html")
		log.Println(t.Execute(w, nil))
	} else {
		r.ParseForm() // 如果注释这句不会有输出 默认情况下,Handler里面是不会自动解析form的,必须显式的调用r.ParseForm()后,你才能对这个表单数据进行操作
		//请求的是登录数据,那么执行登录的逻辑判断
		fmt.Println("username:", r.Form["username"])
		fmt.Println("password:", r.Form["password"])
	}

}
func upload(w http.ResponseWriter, r *http.Request) {
	fmt.Println("method:", r.Method) //获取请求的方法
	if r.Method == "GET" {
		crutime := time.Now().Unix()
		h := md5.New()
		io.WriteString(h, strconv.FormatInt(crutime, 10))
		token := fmt.Sprintf("/x", h.Sum(nil))

		t, _ := template.ParseFiles("upload.html")
		fmt.Println(token)
		t.Execute(w, nil)

	} else {
		r.ParseMultipartForm(32 << 20)
		file, handler, err := r.FormFile("uploadfile")
		if err != nil {
			fmt.Println(err)
			return
		}
		defer file.Close()
		fmt.Fprintf(w, "%v", handler.Header)
		f, err := os.OpenFile("./test/"+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666) // 此处假设当前目录下已存在test目录
		if err != nil {
			fmt.Println(err)
			return
		}
		defer f.Close()
		io.Copy(f, file)

	}

}

func main() {
	http.HandleFunc("/v2", sayHelloName) //设置访问路由
	http.HandleFunc("/login", login)
	http.HandleFunc("/upload", upload)
	err := http.ListenAndServe(":9090", nil) // 设置监听端口
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}

}

三、制作镜像

  1. 准备启动脚本 start.sh
#!/bin/bash
dlv debug --headless --listen=:2345 --api-version=2 --accept-multiclient   $GOPATH/src/web.go
  1. 创建 Dockerfile,并将以上所有文件放在同一个目录中,目录下有 4 个文件
[root@localhost go-debug]# ll
总用量 17708
-rwxr-xr-x. 1 root root 18119408 12月  3 14:52 dlv
-rw-r--r--. 1 root root      187 12月  3 18:55 Dockerfile
-rw-r--r--. 1 root root      107 12月  3 16:21 start.sh
-rw-r--r--. 1 root root     2168 12月  3 14:49 web.go
  1. 编写 Dockerfile
FROM golang:1.12.12

RUN mkdir /web/

COPY ./dlv /usr/local/bin/
COPY ./web.go /go/src
COPY ./start.sh  /web/
RUN chmod   u+x /web/start.sh
WORKDIR /go/src/
ENTRYPOINT ["/web/start.sh"]
  1. 构建镜像
$ docker build . -t web:1.0
  1. 运行镜像
$ docker run -d  -p 9090:9090 -p 2345:2345 --privileged  web:1.0

四、goland 的配置

20191203193707.png

这里有个坑就是,远程被调试的代码和本地代码都必须在 $GOAPTH/src 目录下!!!

goland 单击 debug 按钮 打上断点 接下来就可以远程调试了!!访问接口,就发现代码停在了断点上了

$ curl localhost:9090/v2

20191203194429.png

整个流程结束!

源码地址:

五、后续思路

  1. 修改启动脚本,代码通过挂载的方式加到容器中,应该可以达成不用重复制作镜像的效果
  2. 用 harbor 源码调试,这样就可以进行愉快的 debug 了 而不是光靠想象了
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    492 引用 • 1383 回帖 • 375 关注
  • harbor
    4 引用
  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    476 引用 • 899 回帖 • 2 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...