Debugging a Python project with VSCode and Docker
This guide explains how to setup a Django project and Docker together for debugging sessions within VSCode. We will follow the steps detailed here. The specifics in this document are about Django but it should work all the the same for FastAPI or any dockerized Python code.
Given that you have your Django services setup like so:
version: '3'
services:
api: &api-def
build:
dockerfile: ./Dockerfile
ports:
- "8000:8000"
volumes:
- .:/app
command: python manage.py runserver 0.0.0.0:8000
depends_on:
- db
environment:
- DATABASE_URL=postgres://user@password/api
- DJANGO_SETTINGS_MODULE=api.settings
db:
image: postgres:12.0-alpine
environment:
- POSTGRES_DB=api
- POSTGRES_NAME=postgres
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
ports:
- "5432:5432"
We will use the Debug Adapter Protocol of VSCode to communicates with a debugging server that runs in Docker. For that purpose Microsoft offers an easy to use debugging server for Python called debugpy. You can install it in your dependencies or simply add it at every start debugging session. I chose the second option and added this to my docker-compose.yaml
debug:
<< : *api-def
command: ["sh", "-c", "pip install debugpy -t /tmp && python /tmp/debugpy --wait-for-client --listen 0.0.0.0:5678 manage.py runserver 0.0.0.0:8000 --nothreading --noreload"]
ports:
- 8000:8000
- 5678:5678
You can now start your application with this debugging server attached:
docker compose up debug
Then configure VSCode to use this server. Create a .vscode/launch.json file in your project containing something like this:
{
"version": "0.2.0",
"configurations": [
{
"name": "Remote debug",
"type": "python",
"request": "attach",
"port": 5678,
"host": "localhost",
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/app"
}
]
}
]
}
Once done you should see a new action in your Run and Debug tab (⇧⌘D)

Then add some breakpoints where you want to stop and hit this code path and should get something like this:

Nice that works! That was quite easy wasn’t it?