PAYATHON 2026

如何用 VSCode 调试 Docker Compose 中的 Go 测试?

数据小许

结论

在 test 镜像阶段安装 Delve(dlv),让容器通过 Delve 启动测试,再让 VSCode 以远程调试模式连接 Delve。当前 test 阶段基于 base,而 base 中没有安装 dlv。另外,docker compose run 默认不会发布服务中声明的端口,因此需要加上 --service-ports。

配置测试容器

在 Dockerfile 的 test 阶段安装 Delve,并将容器命令改为使用 dlv test 启动测试:

FROM base AS test
RUN go install github.com/go-delve/delve/cmd/dlv@latest

COPY go.* ./
RUN go mod download
COPY . .

CMD ["/go/bin/dlv", "test", "./...", "--headless", "--listen=:2345", "--api-version=2", "--accept-multiclient"]

dlv test 会构建并运行 Go 测试程序。--headless 启动无界面的调试服务,--listen=:2345 让容器在 2345 端口监听,--accept-multiclient 允许调试客户端连接。只调试某个包时,可以将 ./... 替换为对应的包路径。需要传递测试参数时,在 Delve 参数后加上 --,再写测试参数,例如 -- -test.run TestExample。

在 Compose 的 test 服务中发布调试端口,并为调试器授予所需的 ptrace 权限:

test:
  build:
    context: .
    target: test
  volumes:
    - .:/app
    - gomodcache:/go/pkg/mod
  env_file: .env
  depends_on:
    - db
  ports:
    - "40535:2345"
  cap_add:
    - SYS_PTRACE
  security_opt:
    - seccomp:unconfined

这里将宿主机的 40535 端口映射到容器的 2345 端口。启动调试容器时运行:

docker compose run --service-ports test

使用旧版 Compose 命令时,也可以运行 docker-compose run --service-ports test。--service-ports 会发布 Compose 服务中声明的端口。启动后让终端和容器保持运行,等待 VSCode 连接。

配置 VSCode 远程调试

在项目的 .vscode/launch.json 中添加以下配置:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Attach to Go tests in Docker",
      "type": "go",
      "request": "attach",
      "mode": "remote",
      "host": "127.0.0.1",
      "port": 40535,
      "substitutePath": [
        {
          "from": "${workspaceFolder}",
          "to": "/app"
        }
      ]
    }
  ]
}

在 VSCode 中选择 Attach to Go tests in Docker 并启动调试。substitutePath 会将容器内的 /app 路径映射到本地工作区,否则 VSCode 可能无法将容器中的源码位置对应到本地文件。

断点与注意事项

先在本地测试文件中设置断点,再启动容器并连接调试器。测试运行结束后,Delve 不会自动重新运行测试;需要停止并重新启动测试容器。

配置中的 SYS_PTRACE 和 seccomp:unconfined 用于允许 Delve 在容器中跟踪 Go 测试进程。如果容器运行环境不允许这些权限,调试器可能无法启动或跟踪进程。若测试依赖数据库,确保数据库已就绪。当前的 depends_on: - db 只声明启动依赖,没有配置等待健康检查通过。

备注:内容仅供参考。