我目前面临与在 HashiCorp Vault Go 代码中将根令牌 ID 设置为先前值相关的问题。我尝试在 Docker 容器中使用 dlv debug 来调试应用程序。但是,当尝试在我的 Windows 计算机上运行该应用程序时,它挂起。虽然应用程序最终在 Docker 机器上运行,但我在设置断点时遇到了调试器无法正常运行的问题。
问题是当应用程序在 docker 容器中运行时,如何让 delve 调试器在断点处正确停止
为了更好地理解该问题,我在 GitHub 上附上了该问题的最小重现。
我尝试过的事情
如果你仔细查看日志,你会看到类似这样的内容:
2023-06-14T00:58:37Z debug layer=rpc <- RPCServer.CreateBreakpoint(rpc2.CreateBreakpointIn{"Breakpoint":{"id":0,"name":"","addr":0,"addrs":null,"addrpid":null,"file":"/usr/src/app/minimal_repro/main.go","line":15,"Cond":"","HitCond":"","HitCondPerG":false,"continue":false,"traceReturn":false,"goroutine":false,"stacktrace":0,"LoadArgs":{"FollowPointers":true,"MaxVariableRecurse":1,"MaxStringLen":64,"MaxArrayValues":64,"MaxStructFields":-1},"LoadLocals":{"FollowPointers":true,"MaxVariableRecurse":1,"MaxStringLen":64,"MaxArrayValues":64,"MaxStructFields":-1},"WatchExpr":"","WatchType":0,"hitCount":null,"totalHitCount":0,"disabled":false},"LocExpr":"","SubstitutePathRules":null,"Suspended":false})
2023-06-14T00:58:37Z debug layer=rpc -> *rpc2.CreateBreakpointOut{"Breakpoint":{"id":0,"name":"","addr":0,"addrs":null,"addrpid":null,"file":"","line":0,"Cond":"","HitCond":"","HitCondPerG":false,"continue":false,"traceReturn":false,"goroutine":false,"stacktrace":0,"LoadArgs":null,"LoadLocals":null,"WatchExpr":"","WatchType":0,"hitCount":null,"totalHitCount":0,"disabled":false}} error: "could not find file /usr/src/app/minimal_repro/main.go"
无法在文件上设置断点
/usr/src/app/minimal_repro/main.go
。正确的文件位置是 /usr/src/app/main.go
。
这是您的
.vscode/launch.json
文件:
{
"version": "0.2.0",
"configurations": [
{
"name": "Connect to server",
"type": "go",
"request": "attach",
"mode": "remote",
"remotePath": "/usr/src/app/",
"port": 2345,
"host": "127.0.0.1",
"cwd": "${workspaceFolder}",
"trace": "verbose"
}
]
}
这是目录结构:
├── minimal_repro
│ ├── Dockerfile
│ ├── go.mod
│ └── main.go
└── .vscode
├── launch.json
└── tasks.json
将
"cwd": "${workspaceFolder}"
替换为 "cwd": "${workspaceFolder}/minimal_repro"
将解决该问题。
根据 vscode-go 调试,
remotePath
已弃用。请使用 substitutePath
代替。对于 substitutePath
,.vscode/launch.json
看起来像这样:
{
"version": "0.2.0",
"configurations": [
{
"name": "Connect to server",
"type": "go",
"request": "attach",
"mode": "remote",
"port": 2345,
"host": "127.0.0.1",
"substitutePath": [
{
"from": "${workspaceFolder}/minimal_repro",
"to": "/usr/src/app"
}
],
"trace": "verbose"
}
]
}
关于这段代码:
fmt.Println("dont print the next line")
log.Print("dont print the next line")
fmt.Println("starting web server")
log.Print("starting web server")
生成此输出:
dont print the next line
starting web server
2023/06/14 01:20:31 dont print the next line
2023/06/14 01:20:31 starting web server
这很可能是由于写入缓存造成的。这个问题应该在其他地方讨论。我没有手写讨论的链接,而且由于它对这个问题的主要问题并不重要,所以我暂时忽略它。
这是你的
Dockerfile
:
FROM golang:1.20.5-buster
WORKDIR /usr/src/app
COPY go.mod go.* ./
RUN go mod download && go mod verify
RUN go install github.com/go-delve/delve/cmd/dlv@latest
COPY . .
RUN go build -gcflags="all=-N -l" -v -o /usr/local/bin/app ./...
EXPOSE 2345
EXPOSE 5001
CMD ["dlv","debug","--listen=:2345","--headless=true","--api-version=2","--accept-multiclient","--log","--log-output=rpc,dap"]
# CMD ["dlv","debug","--api-version=2"]
# ENTRYPOINT ["bash"]
请注意,
dlv debug
编译并开始调试当前目录中的主包。它不会执行 RUN go build -gcflags="all=-N -l" -v -o /usr/local/bin/app ./...
生成的那个。如果您想调试预编译的可执行文件,请使用 dlv exec
。