Hungry Beast
Hungry Beast

Reputation: 3725

VS Code Python Django debugging in a dev container

I am developing a Python Django app in a Dockerized container. I have successfully setup remote debugging to attach to my Django server inside of a container. Me configuration is as follows.

launch.json

{
  "name": "Remote Django App",
  "type": "python",
  "request": "attach",
  "pathMappings": [
    {
      "localRoot": "${workspaceFolder}",
      "remoteRoot": "/app"
    }
  ],
  "port": 9001,
  "host": "localhost"
}

manage.py

#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys


def main():
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'llf_api.settings')
    try:
        from django.core.management import execute_from_command_line
        from django.conf import settings

        if settings.DEBUG:
          if os.environ.get('RUN_MAIN') or os.environ.get('WERKZEUG_RUN_MAIN'):
              import ptvsd
              ptvsd.enable_attach(address=('0.0.0.0', 8001))
              print("Attached remote debugger")

    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)


if __name__ == '__main__':
    main()

docker-compose.yml

services:
  api:
    image: ${DOCKER_IMAGE_BASE}:${DOCKER_TAG}
    build:
      context: .
      dockerfile: ./Dockerfile.development
    env_file:
      - .env
    environment:
      - DATABASE_URL=postgres://username:password@db/db_name
    volumes:
      - .:/app
    command: >
      bash -c "wait-for-it --service db:5432
      && python3 manage.py runserver 0.0.0.0:8000"
    ports:
      - "9000:8000"
      - "9001:8001"
    depends_on:
      - db
    tty: true
    stdin_open: true

The problem is that I run VS Code inside of a dev container (the Dockerfile.development above). So VS Code is essentially running within the same container the Django server is running which would make me think I need to attach to the local port (8001) the ptvsd is running on by setting my launch.json to the following:

launch.json

{
  "name": "Local Django App",
  "type": "python",
  "request": "attach",
  "host": "api",
  "port": 8001
}

However this doesn't work. When I try to attach the debugger in VS Code it appears to eventually timeout. Does anyone know how this could be accomplished?

Upvotes: 1

Views: 2265

Answers (1)

Hungry Beast
Hungry Beast

Reputation: 3725

My understanding of how VS Code and my server were running was inherently wrong. The server and VS Code are running off of the same image but NOT the same containers. The containers are running side by side and therefore the local networking is not available to either.

To make this work I realized I needed the VS Code container to access the server's container via the debugging port opened on the host. The only way I know how to do that is by using docker.for.mac.localhost as the host. So all that needed to change from my original setup was the launch.json configuration.

launch.json

{
  "name": "Remote Django App",
  "type": "python",
  "request": "attach",
  "pathMappings": [
    {
      "localRoot": "${workspaceFolder}",
      "remoteRoot": "/app"
    }
  ],
  "port": 9001,
  "host": "docker.for.mac.localhost"
}

VS Code now attaches to port 9001 which has been exposed on the host and connects to the host using docker.for.mac.localhost. It works!

Upvotes: 1

Related Questions