根本原因是端口未映射且dlv监听地址错误;需加-p 2345:2345映射端口,dlv启动用--listen=:2345(非127.0.0.1),GoLand中Host填localhost、Port填2345、Working directory填本地项目绝对路径。

GoLand 连不上容器里的 dlv,Connection refused 怎么办
根本原因是 GoLand 尝试连接 localhost:2345,但这个端口在宿主机上根本没监听——它只在容器内部由 dlv 暴露。你得让容器把调试端口映射出来,且确保 dlv 真正在跑。
实操要点:
- 启动容器时必须加
-p 2345:2345(或在docker-compose.yml的ports下配好) -
dlv启动命令里--listen参数不能写127.0.0.1:2345,必须是:2345或0.0.0.0:2345,否则只绑容器 loopback - 先在宿主机执行
nc -zv localhost 2345,不通就别急着配 GoLand;通了再检查容器日志里有没有API server listening at - 如果用多阶段构建镜像,确认
dlv确实被复制进了最终镜像(比如COPY --from=builder /go/bin/dlv /usr/local/bin/dlv),而不是只留在 builder 阶段
GoLand 的 Go Remote 配置里 Working directory 填什么
填你本地项目根目录的绝对路径,比如 /Users/you/project 或 C:\dev\myapp,不是容器里的路径,也不是相对路径。
为什么必须这样:
立即学习“go语言免费学习笔记(深入)”;
使用 Python 脚本下载 Docker 镜像并打包为 tar 文件。用户说“下载镜像”“拉取镜像”“pull xxx”“帮我下载 nginx 镜像”等时触发。支持 SOCKS5 代理直连(推荐)和国内镜像站加速两种模式。
- GoLand 编译、代码跳转、
go mod分析全部基于这个本地路径做索引 - 容器内代码其实是通过
-v挂载进来的,比如-v $(pwd):/app,那你的 DockerfileWORKDIR就必须是/app,否则go run找不到go.mod - Mac/Windows 用户特别注意:Docker Desktop 默认只共享
/Users或C:\Users下的子目录;项目放在/opt/myproj,挂载后容器里/app是空的 - 如果用了
replace,路径必须是相对路径(如replace example.com/foo => ./foo),绝对路径在容器里必然失效
断点灰色不生效,或者代码改了容器里没更新
90% 是路径错位导致的。GoLand 认为你在编辑 /Users/you/project/main.go,但容器运行时实际读的是挂载后的 /app/main.go,两者只要没对齐,断点就无法命中。
检查步骤:
- 进容器执行
pwd && ls -l,确认当前工作目录和挂载路径一致 - 在 GoLand 的 Run Configuration → Go Remote 里,Host 填
localhost,Port 填你映射出来的调试端口(如2345),Working directory 必须和你本地pwd输出一致 - 改完代码后,观察容器内文件是否实时变化(比如
docker exec -it myapp cat /app/main.go | head -1),没变就是挂载失败或路径写错了 - 如果用
go.work,确保它也在项目根目录,且里面所有use路径都是相对的
调试常驻服务(如 HTTP Server)时不想重启容器
不用杀进程重起 dlv,直接 attach 到已运行的 Go 进程即可,前提是容器里已经装了 dlv 且开了调试端口。
操作流程:
- 进容器:
docker exec -it myapp sh - 查进程 PID:
ps aux | grep 'your_main_binary' - attach 调试:
dlv attach <PID> --headless --listen=:2345 --api-version=2 --accept-multiclient - GoLand 新建一个 Go Remote 配置,Host/Port 和之前一样,不用改 Working directory
- 此时打的断点会直接作用于原进程,服务不中断
注意:dlv attach 要求二进制是用 go build -gcflags="all=-N -l" 编译的(禁用优化),否则变量不可见、行号错乱。CI 构建时记得加上这个 flag。

















