如何在VSCode中调试基于Uvicorn的Docker化Django ASGI应用?
解决Uvicorn运行Docker化Django应用时的debugpy远程调试问题
核心问题分析
之前在manage.py中添加的debugpy监听逻辑依赖Werkzeug(runserver底层服务)的RUN_MAIN/WERKZEUG_RUN_MAIN环境变量,但切换到Uvicorn后,启动流程不再经过manage.py的主逻辑,导致debugpy并未实际启动监听。
正确配置步骤
1. 修改ASGI入口文件(asgi.py),注入debugpy监听逻辑
在asgi.py中添加debugpy配置,同时处理Uvicorn热重载(--reload)场景,避免重复启动监听:
""" ASGI config for Suite-Backend project. It exposes the ASGI callable as a module-level variable named ``application``. """ import os import sys from pathlib import Path # 先加载环境变量和Django配置 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local") # 引入debugpy并配置监听 from django.conf import settings if settings.DEBUG: # 处理Uvicorn热重载:仅在主进程启动监听 if os.environ.get("UVICORN_RELOADER_TYPE") is None or os.getpid() == int(os.environ.get("UVICORN_PID", 0)): import debugpy # 监听所有网卡的9999端口,允许Docker容器外部连接 debugpy.listen(("0.0.0.0", 9999)) # 可选:若需等待调试器连接后再启动服务,取消下面注释 # debugpy.wait_for_client() from django.core.asgi import get_asgi_application # 调整Python路径 BASE_DIR = Path(__file__).resolve(strict=True).parent.parent sys.path.append(str(BASE_DIR / "suite_backend")) django_application = get_asgi_application() application = django_application
2. 确认Docker端口配置
确保Docker已正确暴露9999端口:
- Dockerfile中添加:
EXPOSE 8000 9999 - docker-compose.yml中配置端口映射:
"9999:9999"
3. 保留VSCode的launch.json配置
原有的attach模式配置无需修改,路径映射、端口和主机配置均符合当前场景:
{ "version": "0.2.0", "configurations": [ { "name": "Python: Django", "type": "python", "request": "attach", "pathMappings": [{ "localRoot": "${workspaceFolder}", "remoteRoot": "/app" }], "port": 9999, "host": "127.0.0.1" } ] }
4. 启动与调试流程
- 执行Docker启动脚本,确保Uvicorn服务正常运行
- 在VSCode中选择「Python: Django」调试配置,启动attach
- 设置断点后发起请求,即可触发调试
关键注意事项
- Uvicorn的
--reload模式会启动子进程,必须通过环境变量或进程ID判断,避免子进程重复启动debugpy导致端口冲突 - 启用
debugpy.wait_for_client()可强制等待调试器连接后再启动服务,适合调试应用初始化逻辑
内容的提问来源于stack exchange,提问作者browser-bug
相关产品推荐
相关产品推荐

