Search code examples
python-3.xdockervisual-studio-coderemote-debuggingvscode-debugger

Debugging python in docker container using debugpy and vs code results in timeout/connection refused


I'm trying to setup native debugging for a python script running in docker for Visual Studio Code using debugpy. Ideally I'd like to just F5 and be on my way (including a build phase if needed). Currently I'm bouncing between a timeout caused from debugpy.listen(5678) inlined within the VS code editor itself (Exception has occurred: RuntimeError timed out waiting for adapter to connect) or a connection refused.

I created a launch.json from the documentation provided by microsoft:

launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Attach to Integration (test)",
            "type": "python",
            "request": "attach",
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}/test",
                    "remoteRoot": "/test"
                }
            ],
            "port": 5678,
            "host": "127.0.0.1"
        }
    ]
}

building the image looks like this so far:

Dockerfile

FROM python:3.7-slim-buster as base
RUN apt-get -y update; apt-get install -y vim git cmake

WORKDIR /
RUN mkdir .cache src in out config log
COPY requirements.txt .
RUN pip install -r requirements.txt; rm requirements.txt

#! TODO: config folder needs to be a mapped volume so they can change creds without rebuild
WORKDIR /src
COPY test   ../test
COPY config ../config
COPY src/   .

#?   D E B U G   I M A G E
FROM base as debug
RUN pip install debugpy
CMD python -m debugpy --listen 0.0.0.0:5678 ../test/edu.employer._test.py

#!   P R O D U C T I O N   I M A G E
# FROM base as prod
# CMD [ "python", "/test/edu.employer._test.py" ]

Some examples I found try to simply things with a docker-compose.yaml, but I'm unsure if i need one at this point.

docker-compose.yaml

services:
    tester:
        container_name: tester
        image: employer/test:1.0.0
        build:
            context: .
            target: debug
            dockerfile: test/edu.employer._test.Dockerfile

        volumes:
            - ./out:/out
            - ./.cache:/.cache
            - ./log:/log

        ports:
            - 5678:5678

which I based off a the CLI command: docker run -it -v $(pwd)/out:/out -v $(pwd)/.cache:/.cache -v $(pwd)/log:/log employer/test:1.0.0;

"critical" parts of my script just listen and wait for the bugger:

from __future__ import absolute_import

# Standard
import os
import sys

# 3rd Party
import debugpy
debugpy.listen(5678)
debugpy.wait_for_client()

# 1st Party.  NOTE: All source files are in /src, so we can add that path here for testing
# and batch import all integrations files.  Not very clean however
sys.path.insert(0, os.path.join('/', 'src'))
import integrations as ints

screenshot


Solution

  • You have to configure the debugger with: debugpy.listen(("0.0.0.0", 5678)).

    This happens because, by default, debugpy is listening on localhost. If you have your docker container on another host you have to add 0.0.0.0.