How to locally debug a mono repo of containerized microservices

Alexei Shatz
Neudesic Innovation
6 min readJun 19, 2023
View of my containerized microservices in Docker Desktop

Intro

In this article I will show you how to containerize your microservices using Docker, how to use a docker-compose.yml file to build the images and run them in containers for all of the projects inside your mono repo, and how to attach Visual Studio to each containerized microservice process, so you can debug the code without having to start up each project individually.

What is a Mono Repo?

Quite simply it is a mono repository, where all the codebase for multiple projects, libraries, or services are stored in a single repository.

Here’s a visual example:

If you are already sold on the idea of mono repos, I suggest jumping to the Getting Started section below.

But Why A Mono Repo?

Nietzsche said a person with a why can bear almost any how.

So why would you want a mono repo for microservices? Wasn’t the advantage of microservices mostly in the decoupling? Why on earth then would you want to couple the codebase?

Well, consider the following:

  1. A mono repo can simplify dependency management, as all microservices can share common libraries and dependencies, ensuring consistent versions and reducing duplication across projects
  2. A mono repo can promote reuse and collaboration, as developers can easily access and modify any service or shared library, enhancing the visibility and understanding of the overall system.
  3. With a mono repo, process of testing and deploying can be streamlined, as it allows for more centralized and comprehensive CI/CD pipelines, resulting in faster, more reliable delivery of features and updates.

Mono repos can, however, have a steep learning curve when it comes to getting set up for local development, especially when the microservices are containerized.

Using Docker, and in particular setting up a docker-compose.yml file can simplify the complexity substantially eventually, but getting started can be tricky.

This article will walk you adding Docker to your microservice(s) and how to attach Visual Studio to the process (container) in which your code is running. That way you or your team will know how to debug your code without starting up each individual project within your mono repo.

Getting Started

You will need to download Docker. I recommend Docker Desktop.

If you would like to follow along with my code, you can find it in this GitHub repo.

Creating an API

If you are creating an ASP.NET Core Web API from scratch, select ‘Enable Docker’ as pictured below in the project creation process.

If you have an existing .NET API to which you are adding Docker, right click the solution in the solution explorer and select ‘Add’, then ‘Add Docker Support’.

Dockerfile

The Dockerfile specifies the base image and steps to build a new Docker image for our containerized application. It automates the process of creating a consistent environment by defining application dependencies, environment variables, and other necessary configurations.

IMPORTANT — make sure you change the RUN dotnet publish and RUN dotnet build settings to -c Debug as pictured below. If you leave it in Release mode, our breakpoints will not be hit when debugging (more on this later).

Docker Compose

Next, we’ll go up one directory and create the docker-compose.yml file. That file lives in the below path: {YOUR_REPO_DIRECTORY}/microservices/docker-compose.yml. As you see I named my project microservices. You can pick your own name or use this one.

Here’s the values I input for three microservices (APIs):

Again you can find all of this code here.

We needed to define the containers and which base image will be used inside them. We specify where to find the Dockerfile and which ports to expose on the container.

Once you have your Dockerfile(s) and docker-compose.yml file properly defined, it’s time to open your PowerShell and bulid your images while starting up the containers in which they are running.

In the PowerShell, enter the following command in the root of your project directory:

docker-compose up --build

Here’s what it looks like in PowerShell:

Docker Desktop

Now open Docker Desktop. You should see the list of your images created by selecting Images in the left nav, and you can see the list of your running (or stopped) containers by clicking Containers in the left nav.

Test your code

You can test your containers by clicking the link under the Port(s) column for each container.

Note you may need to add the link in your browser. In my case to hit the GET endpoint in the payment-api-1, for example, I need to go to “http://localhost:5015/Payments” to hit the GET in the PaymentsController.

Debug your code

Good job getting to this point. You can see your containers and you have tested the code in your browser. But what about being able to hit a breakpoint in your code? Afterall we do not have Visual Studio running at all, so why would a breakpoint be hit if we set one on GET /Payments?

We need to attach Visual Studio to the process in which the payment-api-1 container is running.

Here’s how…

In Visual Studio, enter in your keyboard the command: Ctrl+k, Ctrl+o. You should see the Containers window pop up.

Inside the Containers window click the following icon, and select ‘Attach to Process’:

Attach to Process

In the Attach to Process dialog, click ‘Attach’ and then select the checkbox for ‘Managed (.NET Core for Unix).

It may take a while for your debug adapter to attach.

Now set a breakpoint in one of your endpoints. Enter the relevant URL in your browser, and marvel at hitting the expected endpoint.

Conclusion

Embracing the power of mono repos for microservices, this guide has provided a comprehensive walkthrough on how to containerize your microservices using Docker, run them using a docker-compose.yml file, and locally debug the process with Visual Studio. By conquering the initial steep learning curve, you can unlock efficient dependency management, promote code reuse, and streamline CI/CD pipelines. Implement these steps and witness firsthand how debugging in a mono repo environment not only becomes feasible but remarkably straightforward.

--

--

Alexei Shatz
Neudesic Innovation

Consultant at Neudesic, an IBM Company. Seeker of fewer mistakes.