Debugging a Go application inside a Docker container
- Go development with Docker Containers
- Debugging a Go application inside a Docker container (this post)
- Running Go applications using Docker Compose in GoLand
- Using Kubernetes from GoLand
In the previous article of this series, we discussed how to get started using Docker to run our Go applications.
Today, we’ll take a look at how to debug a Go application that runs inside a container.
Creating the Dockerfile for debugging
Using the same repository that we used in the last article, we can switch our branch to the debug branch.
We made a few changes to our Dockerfile.
# Compile stage FROM golang:1.17 AS build-env # Build Delve RUN go install github.com/go-delve/delve/cmd/dlv@latest ADD . /dockerdev WORKDIR /dockerdev RUN go build -gcflags="all=-N -l" -o /server # Final stage FROM debian:buster EXPOSE 8000 40000 WORKDIR / COPY --from=build-env /go/bin/dlv / COPY --from=build-env /server / CMD ["/dlv", "--listen=:40000", "--headless=true", "--api-version=2", "--accept-multiclient", "exec", "/server"]
These changes add Delve, the Go debugger, to the container image and instruct the container to start the application via Delve.
We also need to compile the application with special flags to enable a better debugging experience that results from turning off optimizations from the compiler. And finally, we’ll add both Delve and our binary to the image.
Changing the Run Configuration to allow the debugger to run
Before we start the debugging session, we also need to change how the container runs. In the Bind ports field we’ll add ports 40000:40000. In the Command line options section of the Docker container Run Configuration, we need to add the following value:
This allows us to run a debugger inside the container at the cost of some security features, so it should only be used on debugging containers, but not production ones.
Pro tip: If you don’t want to alter your original Docker container or the Run Configuration used for it, then you can create a duplicate Dockerfile and a duplicate Run Configuration. Use the Copy refactoring on the Dockerfile to copy it to a new file named Dockerfile.debug.
If you’ve never used the .debug extension before, the IDE will ask you how to associate the file. In the file pattern, use Dockerfile.debug and then select the Dockerfile type in the list that appears.
Starting the debugger
To start the debugger, place breakpoints as you normally would, then create a new Go Remote Run Configuration, and the debugger will start as usual.
As you’ve probably noticed, there’s no need to add file path mapping manually to the IDE, as it will automatically know how to map the source code from the container to the host.
Note: This works as long as the binary is not stripped of debugging information.
That’s it for today. We’ve discussed creating and running Docker configurations, which allow us to debug Go applications inside containers.
In our future articles, we’ll look at how to start and debug our application using Docker Compose and Kubernetes.
Subscribe to Blog updates
Thanks, we've got you!
Does Machine Learning in Go Have a Future?
In this article, you'll explore the challenges of actively using Go for Machine Learning.
OS in Go? Why Not?
In this article, you'll learn why languages like C have a stronghold over OS development and whether writing an OS using Go is possible.
Comparing database/sql, GORM, sqlx, and sqlc
This article compares the database/sql package with 3 other Go packages, namely: sqlx, sqlc, and GORM. The comparison focuses on 3 key areas – features, ease of use, and performance.