Using VSCode in Docker Containers

VSCode is one of the most popular Integrated Development Environments to code. Docker containers are arguably the most efficient way to develop services, yet debugging and testing running services inside the container has always been a pain point. Why not use the full benefit of our beloved IDE, VSCode, for that? VSCode can be attached, yes attached not connected, to a running container as if it is opened within the container. Then it is possible to debug line by line with breakpoints in any kind of running service.

I’m Huen, Software Developer 3 on the Buying Intelligence squad @SSENSE where we develop services that support the buyers and the company to make data-driven decisions. SSENSE is a renowned tech and data-driven company, and we continuously strive to be more efficient and adapt to state-of-the-art technologies. All our efforts pay off by delivering no downtime services to our worldwide clientele.

In a typical situation with a small microservice, it would be enough to debug based on printed logs. We, the Buying Intelligence squad, however, needed to find a way to debug very complex logic with lots of internal data transformation and computation. The algorithms were initially provided by our Data Scientists and it was our responsibility to enhance its value as a service. It would have taken excessive effort to find bugs and ensure its functionality without this debugging technique.

This article will explain how to use VSCode attached to a running container, including:

  • How to set up a basic server application with Falcon
  • How to attach VSCode to a container
  • How to set up and debug a running application in a container
  • How to set up and debug unit tests in a container

Setting up a Basic Server Application with Falcon

We are using Falcon in this example but it is also applicable with other frameworks such as Flask.

Set up docker image and container

Let’s begin by creating a docker image for our simple application.

We’ll use a Makefile to facilitate running long commands. If you want tips on how to use Makefile, here is a great article written by my colleague on how to use Makefile in development.

Now you are ready to build a Docker image, run, and remove a container for our application with simple commands, e.g.make build-image to build a docker image.

Create an application

Now it’s time to create a simple application based on the Falcon tutorial.

< Folder structure >
vscode-with-container-falcon/
├─ app/
│ ├─ __init__.py
│ ├─ images.py
│ ├─ server.py
├─ .gitignore
├─ Dockerfile
├─ Makefile
├─ README.md
├─ requirement.txt

First, we need to add packages to the requirement.txt

Create a resource and add it to the application.

Create a server and add it to the application.

Add api command to the Makefile.

It’s done! Let’s run it with the following commands:

  1. Build a docker image: make build-image
  2. Run a container: make run-container
  3. Get in the container via bash: make bash
  4. Run the service: make start-api

Now your application is running in a container. You can check if it is running by sending a simple http request:

vscode-with-container-falcon git:(master) ✗ curl http://localhost:8080/images
{"images": [{"href": "/images/1eaf6ef1-7f2d-4ecc-a8d5-6e8adba7cc0e.png"}]}%

If everything is running smoothly, let’s stop the service for now using ctrl+C

Debugging With Attached VSCode to a Container

Attach VSCode to a container

To attach VSCode to a container, install the following two extensions:

You should now be able to see the docker tab on the left-hand side of VSCode. Under the Container drop down you’ll see your running container. You can right click on the container and select ‘Attach Visual Studio Code’.

This will open a new VSCode window and show its progress on the bottom right-hand side.

Once this is done, you will be able to see the following indication on the bottom left-hand side confirming that the VSCode is now attached to the container.

It’s done! You have attached VSCode as if it is open inside the container.

Set up and debug

We’re not quite finished yet. There are a few more steps left. First, let’s open the working folder. As you can see, you’re clearly in the container.

The attached VSCode is running in an isolated environment, which is separated from your local VSCode, meaning that you need to install extensions once again. Let’s install the following essential Python extensions. It may require you to re-open VSCode.

Alright, now you have opened your working folder and installed the necessary extensions in the attached VSCode. Let’s complete the final step to set up the debug launcher.

You’ll either need to create the .vscode/launch.json file or follow the instructions below to create one:

  1. Click the ‘Run and Debug’ button on the bar on the left, then select ‘create a launch.json file
  2. Select ‘Python > Flask > App.py’. We have chosen Flask just to create a template for our application
  3. Change the launch.json as per the below example

Now you are ready to debug. Let’s do it.
Go to the images.py and add a breakpoint.

Run the debug by clicking the button below.

Now let’s run the http request once again.
curl http://localhost:8080/images

Voila! You are now running code in real-time.

You now have full control of your code and service to go as deep as you want with real-time variables and call stack changes. This totally unlocks the potential to debug any sort of complex logic.

Running and Debugging Unit Tests on the Attached VSCode

It’s time to jump into unit tests. Have you ever been trapped searching for what went wrong in your unit tests, only to find out the cause was based on short error messages? We can run the unit tests visually in VSCode and debug each one of them independently. Here’s how. Reminder, we are still in the container.

First, let’s create a simple helper function to test.

Then we need to create a unit test.

Let’s config the unit tests by either:

  1. creating .vscode/settings.json
  2. creating one by selecting ‘Python: Configure Tests’ in Command Palette (Command + Shift + P in Mac) followed by ‘Unittest > tests > test*.py’

Then Change the file as per the below example.

We should be all set. But wait, nothing comes out in testing?

This is because you didn’t add __init__.py to your test’s modules. Without __init__.py it doesn’t recognize it, so let’s add it.

├─ tests/units/
│ ├─ __init__.py
│ ├─ app/
│ │ ├─ __init__.py
│ │ ├─ test_helper.py

You now have your tests! You can run these tests altogether or individually. It clearly shows which test is failed and/or passed. Moreover, you can debug it by just clicking the Debug Tests button beside a test.

Conclusion

Congratulations! You have unlocked the full potential of VSCode attached to a running container. Happy bug hunting!

Resource:
Sample code in Github — https://github.com/heons/vscode-with-container-falcon

Leave a Reply

Your email address will not be published. Required fields are marked *