Configuring Delve Debugger in a Go DevContainer

Delve is Go's debugger, and running it inside the devcontainer lets you set breakpoints against the real container runtime. This page configures Delve for both launching a program and attaching to a running Go service, with the source mapping right.

Prerequisites

You need a Go devcontainer with the Go extension and Delve.

  • A Go Feature pinned in the container.
  • The Go extension (installs Delve) in the container.
  • A debug build so symbols are present.

Delve prerequisitesYou need the Go extension, a debug config, headless Delve for services, and binding breakpoints.Go extensioninstalls dlvLaunch/attachconfigHeadless dlvfor servicesBreakpointsbind

Step-by-Step Implementation

  1. Ensure the Go extension (and Delve) are in the container.
{ "customizations": { "vscode": { "extensions": ["golang.go"] } }, "remoteUser": "vscode" }
  1. Launch a program under the debugger (the extension provides a launch config).

  2. Or run a service headless with Delve and attach.

dlv debug --headless --listen=:2345 --api-version=2 ./cmd/app
  1. Attach the editor and set breakpoints.
{ "name": "attach", "type": "go", "request": "attach", "mode": "remote", "port": 2345 }

Delve modelDelve runs in the container, debugging the container binary via launch or headless attach.Delve in containerdebugs container binaryLaunch modedirect debugHeadless attachfor running servicesDebug buildbreakpoints bind

Common Pitfalls

Delve issues are an optimized build or missing headless server for services.

Delve triageA triage path from non-binding breakpoints to a working Delve attach.Do breakpoints bind?NOBuild with debug info (no -ldflags -s-w)Debugging a running service?YESRun dlv headless and attachGo debugging works

SymptomRoot CauseRemediation
Breakpoints don't bindOptimized build, symbols strippedBuild without -s -w; keep debug info
Can't attach to a serviceNo headless Delve serverRun dlv --headless --listen
Attach refusedPort not forwardedForward the Delve port
Wrong line mappingStale build vs sourceRebuild so the binary matches sources

Conclusion

Debug Go where it runs: put Delve in the container via the Go extension, and either launch under it or run it headless and attach to a service. Build with debug info so breakpoints bind, and you're debugging the exact binary the container executes.

Launch vs attachLaunch directly for programs; attach headless Delve for running services.Launch modeDirect debugSimple programsNo extra serverAttach modeHeadless dlvRunning servicesForwarded port

FAQ

Why won't my Go breakpoints bind? Usually the binary was built optimized with symbols stripped (-ldflags "-s -w"), so Delve has nothing to map breakpoints to. Build with debug information (the default debug build) so symbols are present, and ensure Delve runs in the container against that binary.

How do I debug a running Go service in the container? Start it under Delve in headless mode (dlv debug --headless --listen=:2345 --api-version=2), forward the port, and use a remote attach configuration. The editor connects to the live service and you set breakpoints without restarting it under the debugger.

Does Delve run on the host or in the container? In the container — the Go extension installs Delve into the container, so it debugs the container's binary against the container's Go toolchain. That keeps the debug session faithful to what actually runs, including any container-specific build tags or environment.