使用VisualStudioCode在远程调试中Docker和Golang
首先
由于一直无法获取到关于在Docker中封装Golang环境时如何进行调试的信息,所以我决定总结一下。
验证环境
主机方
-
- Windows10 + Boot2Docker + VisualStudioCode
- Sierra + Docker for Mac + VisualStudioCode
容器一方
- golang:onbuildを使用(執筆時点ではgolang 1.7)
关于Golang的调试器
由于在VisualStudioCode中使用Delve,因此我会使用Delve。在查看文档和问题时,发现还支持远程调试,甚至可能支持Docker,这是导火索。
关于Docker的远程调试
似乎可以进行远程调试,以此为基础为Golang写代码重写。
使用 Docker 进行实时调试。
准备的文件
$GOPATH/src/github.com/user文件夹中有以下文件:
– .vscode文件夹
– launch.json文件
– docker-compose.yml文件
– Dockerfile文件
– main.go文件
// main.go
package main
import (
"fmt"
"log"
"net/http"
"github.com/garyburd/redigo/redis"
)
func main() {
redi, err := redis.Dial("tcp", "redis:6379")
if err != nil {
log.Fatal(err)
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
res, err := redi.Do("incr", "counter")
if err != nil {
w.WriteHeader(500)
w.Write([]byte(err.Error()))
return
}
if res, ok := res.(int64); ok {
w.Write([]byte(fmt.Sprintf("counter: %d", res)))
} else {
w.WriteHeader(500)
w.Write([]byte("unexpected value"))
}
})
log.Fatal(http.ListenAndServe(":5000", nil))
}
# Dockerfile
FROM golang:onbuild
RUN go get github.com/derekparker/delve/cmd/dlv
# docker-compose.yml
app:
build: .
ports:
- "5000:5000" #golang webserver用のポート
- "5050:5050" #delve用のポート
links:
- redis
volumes:
- ".:/go/src/app"
privileged: true # Delveで必要なので付与します。セキュリティ面から本番環境では使うべきではありません。
command: dlv debug --headless --listen=:5050 --log
redis:
image: redis
{
"version": "0.2.0",
"configurations": [
{
"name": "Remote",
"type": "go",
"request": "launch",
"mode": "remote",
"remotePath": "/go/src/app", //コンテナ内のパス
"port": 5050, // dlv debugのポートを指定(WEBのポートではない)
"host": "192.168.99.100", //左の設定はToolBoxを使った場合のDocker MachineのIP. for Macの場合はlocalhostでよかった.
"program": "${workspaceRoot}", //${workspaceRoot} = $GOPATH/src/github.com/user
"env": {},
"args": [],
"showLog": true
}
]
}
主要的.go文件是参考了这篇文章。
使用Redis来递增和显示数字的简单处理。
参考:使用Docker构建的Golang开发环境。
进行远程调试
启动容器
在main.go的当前位置构建并启动容器。
> docker-compose build
redis uses an image, skipping
Building app
Step 1 : FROM golang:onbuild
# Executing 3 build triggers...
Step 1 : COPY . /go/src/app
Step 1 : RUN go-wrapper download
---> Running in ff0ae2dae819
+ exec go get -v -d
github.com/garyburd/redigo (download)
Step 1 : RUN go-wrapper install
---> Running in d778a728a336
+ exec go install -v
github.com/garyburd/redigo/internal
github.com/garyburd/redigo/redis
app
---> 0b0ffd816054
Removing intermediate container ff0ae2dae819
Removing intermediate container d778a728a336
Removing intermediate container 677062574a96
Step 2 : RUN go get github.com/pilu/fresh
---> Running in 06b38d625b20
---> 3bc412d615be
Removing intermediate container 06b38d625b20
Step 3 : RUN go get github.com/derekparker/delve/cmd/dlv
---> Running in 10b51b638607
---> 206e4fb5f2c0
Removing intermediate container 10b51b638607
Successfully built 206e4fb5f2c0
> docker-compose up -d
> docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------------------------------
user_app_1 dlv debug --headless --lis ... Up 0.0.0.0:5000->5000/tcp, 0.0.0.0:5050->5050/tcp
user_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
只要有两个容器站起来就可以了。
用VisualStudioCode开始调试
听说,你可以使用VisualStudioCode从容器中启动代码。
首先,打开VisualStudioCode的调试视图,并在想要设置断点的代码处设置断点。

然后将左上方的调试切换到远程并运行。
※若成功,下方的状态栏将变为橙色。

当达到这种状态时,将启动容器内的main.go并在浏览器中打开IP地址进行访问(应该可以使用docker-machine的IP地址或localhost)。
将在设置断点的位置处触发断点。

除了常规的调试之外,您可以按照自己的喜好进行调试。
未能解决的问题
尽管我们已经可以进行远程调试,但仍然存在以下问题,使用仍然不够方便。
-
- 在执行过程中无法更改断点
-
- 在停止远程调试后重新执行会导致调试器挂起
- 需要将Docker的privileged设置为True,这是不可取的。
1. 对于问题 1 ,如果进行重新启动或热部署的话,应该是可行的。
2. 对于问题 2,在 VSCode 中停止后无法开始新的远程调试,最终需要重新启动容器。(容器内残留的进程似乎是个问题,无法进行杀掉。)
3. 对于问题 3,不清楚 Delve 需要哪些权限,目前已经提供了全部权限,但从安全的角度来看并不好。可能需要采取只针对开发环境的对策。
有没有什么好的方法呢?
最后
我希望能够建立起利用VisualStudioCode和Golang的高度兼容性,既能作为编辑器使用,又能像集成开发环境一样使用,非常易用。
同时,我还想通过使用Docker来确立一种开发方法,以提高效率。