Seamless Multi-Container Live Debugging in VSCode | DevContainers on Steroid

Kshitij Sharma
Microsoft Azure
Published in
4 min readFeb 15, 2021

This article will walk us through remote live debugging a multi-container workspace or monorepo style workspaces for containerized applications.

Advantages

▹ The setup debugs all repositories in a single VS Code Window without needing to switch between windows for debugging.

▹ Single Docker orchestration layer via Docker-compose

▹ Reduces dependencies on VsCode for multi-root workspaces

▹ Support for Hot Reloading of Source Code

▹ Cross-Language Support — Your applications can be in any language Node, Python, Go, C#, etc.

▹ This is typically useful for monorepo styles and for building Azure Teams Bots using Bot Framework which requires setting up ngrok configuration for local debugging.

Here’s what we’ll need

★ Visual Studio Code

★ Docker

★ NodeJS Application — We will use two simple NodeJS applications as part of the walkthrough

Source Code is hosted on Github.

Folder Structure

Let us delve into the folder structure of the repository:

  1. We have two services — serviceA and serviceB at the root level. The source code for each of them resides in the respective folders.

serviceA

The serviceA is a simple nodeJS server listening on port 3000. serviceA executes /play API endpoint on serviceB for a response on its /result endpoint controller. It consists of a Dockerfile that runs the application.

serviceB

service B runs on port 3001. It consists of a Dockerfile that builds and runs the NodeJS application. The /play endpoint controller sends a simple response back to the caller service( serviceA )

2. There is a docker-compose file at the root level orchestrating both the services. serviceB is within the network of serviceA.

We have exposed two more ports 5000(serviceA) and 5001(serviceB) for nodemon.

nodemon is a tool that helps develop node.js based applications by automatically restarting the node application when file changes in the directory are detected.

3. The .vscode folder contains launch.json which has a launch configuration for debugging the applications. More on that later.

Let's start by spinning up both the applications. Open the repository in VSCode and the following commands in the terminal.

docker-compose build --no-cache
docker-compose up

Remote Debugging

Now both services are running and listening on ports 5000 and 5001 for debugging. Let's attach debuggers to different services to debug them in parallel.

  1. Navigate to Debugger in VSCode by clicking on the Debug Icon.

In the source code, we have a launch.json which has a configuration for attaching to debuggers on the nodemon port with request type as attach.

In the source code, we have a launch.json which has a configuration for attaching to debuggers on the nodemon port with request type as attach.

remoteRoot is set to the path of the code directory inside the container

localRoot is set to the path of the code directory on the host machine.

This helps VSCode to observe file changes for debugging.

2. Run the applications in debug mode by clicking the Play Button for both ServiceA API and ServiceB API one after the other.

And you are done, now both applications are running in debug mode in the same Visual Studio Code window with hot reload.

Let's play around with it and start by applying a breakpoint at line 7 in serviceA API and line 6 in serviceB API code in index.js of respective services.

Also, change the message on line 7 in index.js for service A and save the file. We see the following changes after the file is saved :

  • Docker detected the filesystem change event and proxied it through to the container.
  • nodemon detected the event and restarted the application.
  • VSCode reattached the debugger to both applications.

We will now execute a curl request to serviceA:

curl localhost:3000/result

and we see the debugging breaking at two different points as applied by us.

Breakpoint in serviceA
Breakpoint in serviceB

That’s it! Go Power your debugging :)

--

--