Debugging Go using Delve, Docker and VS Code
By: Mike Kaperys
Tags: Visual Studio Code, Golang, Docker, Debugging, Delve

Debugging a program can often be frustrating. Particularly so when your program is compiled and running inside a Docker container — it can seem like you spend more time compiling than actually fixing the bug! Using a debugger can alleviate some of the pain points associated with debugging.

Delve is a debugging tool for the Go programming language. It’s designed to be simple and not get in the way.

In this post we’ll discuss how you could use Delve and Visual Studio Code to debug a Go application running inside a Docker container.

Getting started

To use Visual Studio Code with Delve we’ll need the vscode-go extension. To install this, open the quick command palette ( CTRL+P ) and enter ext install ms-vscode.Go .

If you’d like to follow along with this article you can download the code from GitHub: https://github.com/kaperys/blog/tree/master/delve-into-docker

Dockerfile

To begin debugging our application we’ll need to first download Delve. The easiest way to download Delve is to go get it. Once we have Delve installed, we can use the dlv debug command to being the debugging process.

The dlv debug command compiles the program with the necessary flags, starts the program and attaches to the running process. Since we’re going to be running the Delve API inside a Docker container and using an external client to connect, we’ll need to start Delve using the --headless flag and tell it which port to listen on — we’ll use --listen=:40000 for this.

Here’s an example Dockerfile which does everything we need:

We can build the container using docker build -t delve-into-docker-app . , or, if you’re following along with my code, you can use make build .

Now we’ve built the container we’re ready to start it. We can use the following command to start the container (or make run if you’re following along).

docker run --rm --publish 40000:40000 --publish 1541:1541 --security-opt=seccomp:unconfined --name delve-into-docker delve-into-docker-app

This command tells Docker to run the delve-into-docker-app image and name it delve-into-docker . It publishes ports 40000 (for the Delve API server) and 1541 (for our program) and tells Docker not to use the default seccomp profile, which is necessary to allow dlv to fork processes.

Visual Studio Code

To use Visual Studio Code to debug we’ll need a launch.json file. This file contains all the information Visual Studio Code will need to connect to and control Delve. Visual Studio Code will look for this file in the .vscode directory.

Here’s an example launch.json file which contains the configuration necessary to connect Delve running on our Docker container:

Let’s break down what each property does:

name sets the name of the launch configuration in Visual Studio Code. This name appears in the debug launch configuration drop-down menu.

sets the name of the launch configuration in Visual Studio Code. This name appears in the debug launch configuration drop-down menu. type tells Visual Studio Code which debugger extension to use. We’re using Delve which is included in the vscode-go extension.

tells Visual Studio Code which debugger extension to use. We’re using Delve which is included in the extension. request tells Visual Studio Code what to do with your launch configuration. It determines if Visual Studio Code should attempt to launch a new debugger process or attach to an existing one.

tells Visual Studio Code what to do with your launch configuration. It determines if Visual Studio Code should attempt to launch a new debugger process or attach to an existing one. mode is specific to the Go debugger and determines the behaviour of the underlying Delve process. Since we’re going to be connecting to a remote Delve API server, we’ll use “remote”. There’s more information regarding the mode property on the vscode-go wiki pages.

is specific to the Go debugger and determines the behaviour of the underlying Delve process. Since we’re going to be connecting to a remote Delve API server, we’ll use “remote”. There’s more information regarding the property on the wiki pages. remotePath tells Visual Studio Code where to find your application code on the remote server. This is necessary for Visual Studio Code to be able to map your local breakpoints to ones on the remote server.

tells Visual Studio Code where to find your application code on the remote server. This is necessary for Visual Studio Code to be able to map your local breakpoints to ones on the remote server. port tells Visual Studio Code which port the remote API server is listening on. This must match the port we published when starting our Docker container.

tells Visual Studio Code which port the remote API server is listening on. This must match the port we published when starting our Docker container. host tells Visual Studio Code where the API server is listening. This value must be the IP address of your running Docker container. You can find the IP address using the following command: docker inspect delve-into-docker --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' .

tells Visual Studio Code where the API server is listening. This value must be the IP address of your running Docker container. You can find the IP address using the following command: . program tells Visual Studio Code where your program source code is. Since ours is in the root directory of the project, we can use “${workspaceRoot}”.

tells Visual Studio Code where your program source code is. Since ours is in the root directory of the project, we can use “${workspaceRoot}”. showLog simply tells Visual Studio Code to show the output from the Delve debugger.

Debugging

Now we’re set up we’re ready to begin debugging! Here’s the demo program we’ll use:

To start with we’ll add a breakpoint at line 11. To add a breakpoint in Visual Studio Code, click just to the left of the line numbers in the editor or press SHIFT + F9 to add one to the current line.

It’s important to note that Delve will only allow us to add a breakpoint whilst the application isn’t running. This means we’ll need to add our first breakpoint before starting the debugger. After this, we can add breakpoints whilst the program is paused.

To start debugging either press F5 or go to Debug > Start Debugging in the menu. The blue status bar at the bottom of the editor will go orange once Visual Studio Code is connected to the Delve API server.

If you’re struggling to get Visual Studio Code connected to Delve there’s a helpful “Troubleshooting” section in the vscode-go wiki pages.