Debugging Dockerized Go Applications with VS Code

Ken Aqshal
Level Up Coding
Published in
7 min readMar 7, 2023

--

Cover image by author

For developers, debugging becomes a crucial and challenging aspect of software development. It’s like being a detective, searching for clues and piecing together the story of what went wrong in your code. But, just like any detective story, it’s also a challenge. Debugging in a containerized environment, like Docker, adds an extra layer of complexity. However, with the right tools and approach, debugging Go applications in Docker containers can be a straightforward and rewarding experience.

Go, also known as Golang, is a powerful open-source programming language known for its simplicity, efficiency, and reliability. But, when it comes to deploying and managing applications, there’s a better solution — Docker containers, especially when microservices continue to gain popularity. Docker containers provide a standardized, isolated environment for your Go applications, making deployment and management a breeze.

In this post, you will explore how to debug Go applications in Docker containers using Visual Studio Code. this post will cover the necessary steps for setting up the debugger and walk through the process of debugging a Go application both with docker and docker-compose. By the end of this post, you should better understand how to debug Go applications in Docker containers using Visual Studio Code.

So, if you’re ready to elevate your debugging game and make your life as a developer easier, keep reading! you won’t regret it.

Prerequisite

  • Golang 1.16 or higher
  • Docker
  • Visual Studio Code

Setting up

Firstly, ensure that all prerequisites are installed. Once that is done, proceed with setting up the project. In this blog, we will use gofiber for a sample application to debug Go applications. Follow the steps below:

  1. Create app folder
mkdir go-debugger && cd go-debugger

2. Add the following content to Dockerfile file

# syntax=docker/dockerfile:1
FROM golang:1.18-alpine

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download

COPY . .

RUN go build -o go-debugger .

EXPOSE 3000

CMD ["/app/go-debugger"]

3. Build the image from the code

docker build --tag go-debugger-image .

4. After finishing the build, we can verify it by running command below in the terminal

docker images --filter "reference=go-debugger-image"

it will show the information about the local image that you create, and the information should be like this

Search docker image. Image by author

5. After we check the image, let’s run your image as a container with this command

docker run -d -p 3000:3000 --name go-debugger-container go-debugger-image

6. Verify if the container is successfully run with the command

docker ps --filter "name=go-debugger-container"

the display information should be like this

Search docker container. Image by author

7. Check by open http://localhost:3000/, the page will show this to you

Test the API. image by author

But how to debug it?

Great work verifying everything is working! Now, let’s take it a step further and debug the app inside the Docker container. But before we dive into debugging, we need to create a separate Dockerfile version specifically for debugging purposes. This way, we’ll have a “normal” Dockerfile to run the app as usual, without debug mode.

Why do we need to separate the Dockerfile? We’re using a third-party package called delve to enable us to debug the Go app inside the Docker container. And because we’re using an external package, we need to configure the Docker image differently to ensure that delve works properly.

So, let’s get ready to debug our app and unravel any issues lurking inside the container!

  1. Let’s create a dockerfile for debug only
touch Dockerfile.debug

2. Add the following content to Dockerfile.debug file

FROM golang:1.18-alpine

EXPOSE 3000 4000

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download

COPY . .

RUN CGO_ENABLED=0 go install -ldflags "-s -w -extldflags '-static'" github.com/go-delve/delve/cmd/dlv@latest

RUN CGO_ENABLED=0 go build -gcflags "all=-N -l" -o go-debugger .


CMD [ "/go/bin/dlv", "--listen=:4000", "--headless=true", "--log=true", "--accept-multiclient", "--api-version=2", "exec", "/app/go-debugger" ]

there are some commands that you must be aware of:

  • --listen=:4000 this is will be the port that your debugger(delve) listen to. that's why we expose 2 ports in EXPOSE 3000 4000
  • CGO_ENABLED=0 is required for not making the delve configuration become dynamic compiled
  • -gcflags=all="-N -l" is used for disable inlining and optimizing because it can interfere with the debugging process

3. Next step is you must build a new image with Dockerfile.debug configuration

docker build --file Dockerfile.debug --tag go-debugger-image . 

4. After finish build the image, the next step is to remove the previous container because we can’t have 2 containers with the same name

docker container rm go-debugger-container

5. After deleting, let’s run your image as a container

docker run -d -p 3000:3000 -p 4000:4000 --name  go-debugger-container go-debugger-image

6. After successfully running your container. now let’s prepare the debugger in VS Code

Create debugger config. image by author

7. After that, you will have a launch.json , Add the following content to it

{
"version": "0.2.0",
"configurations": [{
"name": "Go Containerized Debug",
"type": "go",
"request": "attach",
"mode": "remote",
"port": 4000,
"host": "127.0.0.1"
}]
}

8. Now, let’s try to set some breakpoints and run the debugger

Set breakpoints and run debugger. Image by author

9. After you run the debugger, let’s verify it with open http://localhost:3000/test . it's should be automatic redirect to your vs code like this

Debugging process. Image by author

Awesome! You’ve successfully set up your code for debugging in a Docker container. Now, get ready to dive deep into your code and uncover any pesky bugs that have been hiding!

Debugging like a Pro with Docker Compose

But hold on a minute…what if you want to take it to the next level and run your app with Docker Compose? After all, many modern development workflows rely on container management. Well, fear not! Setting it up with Docker Compose is easy as pie, and I’m here to show you how it’s done. Let’s get started!

1. Make sure that no application will use ports that we expose in Dockerfile.debug. In this case, you expose ports 3000 and 4000. if there's an application that used the port, stop it

2. let’s make the docker-compose.yml with command

touch docker-compose.yml

3. Add the following content to your docker-compose.yml

version: "3.9"
services:
app:
build:
context: .
dockerfile: Dockerfile.debug
ports:
- "3000:3000"
- "4000:4000"

4. Now, let’s create and run the container with the command

docker compose up

5. Now let’s run the debugger in VS code like in step 8 before

Set breakpoints and run debugger. Image by author

6. Verify the debug with an open URL http://localhost:3000/test and it will redirect to VS code like this

Debugging process. Image by author

Fantastic! You’re ready to take your debugging skills to the next level with Docker Compose. By leveraging this powerful tool, you’ll be able to manage your containers more effectively and streamline your development workflow. Whether you’re dealing with complex code or simply looking to improve your debugging abilities, Docker Compose is an excellent tool in your arsenal. So, what are you waiting for? It’s time to debug like a pro!

Conclusion

here is a wrap-up about this blog post that you’ve read

  • Debugging is possible in Golang with the third-party package Delve
  • You can debug the app with delve on both docker and docker-compose with some additional.
  • I recommend separating the “normal” Dockerfile and “debug” Dockerfile because there’s a custom configuration to make Delve run smoothly, and changing the environment becomes easier.

Reference

Enjoyed this post?

Check out some of my other articles:

Originally published at https://www.kenaqshal.com on March 7, 2023.

Level Up Coding

Thanks for being a part of our community! Before you go:

🚀👉 Join the Level Up talent collective and find an amazing job

--

--