Remote Debugging Django Project in Docker

In the last post I described how to setup Django and Apache in Docker container. In this post I will describe how to remote debug the Django application running in the same setup. If you look at the Dockerfile of the project (in the last post), you would see that it installs ptvsd package – this package helps to debug Django applications running remotely using Visual Studio Code.

Install Visual Studio Code, if you haven’t installed it already. Then install VS Code extension for Python. I have installed this extension by Don Jayamanne, and it supports debugging of Python applications. If you don’t know how to install extensions in VS Code, this video might help you.

To enable remote debugging of Django application, or Python applications in general, you need to run ptvsd server on the machine where Django is configure, which in our case is a Docker container. You need to embed following code snippet in your Django app, and it needs to run only once, because it listens to a port.

import ptvsd

ptvsd.enable_attach("my_secret", address = ('0.0.0.0', 3500))

The above snippet starts ptsvd server, that listens on port 3500. We configured Python to run in Apache2 using mod-wsgi in the Docker container, but I haven’t found a way to embed the above code in a Django application in this setup, where it would run only once (if it is run multiple times, it will try to attach to the same port and that would fail). So far the best way I have found to debug Django application remotely in Docker is to start Django development server on a different port (than one where Apache is listening) and embed the debugger code in manage.py. You run the development server by running manage.py, for example –

$ python manage.py runserver 0.0.0.0:8080

This will run the dev server on port 8080. Insert the code to start ptvsd server in manage.py, at the end of ‘try’ block, just above ‘except’ block. Next, start the dev server. But there is one problem. If you change any application code, dev server will try to reload, and in the process it will execute the code to start the server, and since server is already started, it will fail with port in use error. I tried using is_attached API of ptvsd to check if debugger is already attached, but that did not work. So for now, I have disabled reload using –noreload switch –

$ python manage.py runserver --noreload 0.0.0.0:81

It is a big inconvenience to restart the server every time you make changes to the code, but I haven’t found any solution for this so far.

Remember that we have mapped three ports in docker-compose.xml

ports:
      - '8005:80'
      - '3500:3500'
      - '8006:81'

Port 80, at which Apache is listening is mapped to 8005. Port 3500, at which ptvsd debugger server is listening is mapped to the same number in the host machine. And port 81, at which our development server is running is mapped to 8006. So to access the development server, you need to open http://localhost:8006 from the host machine.

Once the server is running, we need to configure the debugger in VS Code. Click debug icon in the activity bar (on the left)

Initially there may not be any configuration present. Click on the drop down and select ‘Add Configuration’. Alternatively you can select Debug | Add Configurations menu option. This will create a new file launch.json with many configurations for Python debugging. We are interested in a configuration called ‘Attach (Remote Debug)’. In this configuration, change localRoot, remoteRoot and port. For the setup being discussed in this post, the configuration should look like –

{
    "name": "Attach (Remote Debug)",
    "type": "python",
    "request": "attach",
    "localRoot": "${workspaceRoot}/www",
    "remoteRoot": "/var/www/html",
    "port": 3500,
    "secret": "my_secret",
    "host": "localhost"
}

Run the development server, if it is not already running.

  1. Start the docker container – ‘docker-compose up’
  2. Open a bash shell in the container – ‘docker exec -it django-apache2 bash’
  3. Go to the project folder – ‘cd /var/www/html/django_demo_app/demo_site’
  4. Run Django dev server – ‘python manage.py runserver –noreload 0.0.0.0:81’

From you host machine browse to http://localhost:8006 and make sure the application is working.

In VS Code, open /www/django_demo_app/demo_site/app1/views.py file and set breakpoint on line 16, in index method (click in the left margin on the line to set breakpoint). Click on debug icon in the left activity bar and select ‘Attach (Remote Debug)’ configuration and click play button.

Open the application link, http://localhost:8006, in the browser. You should see execution stopped at the breakpoint in VC Code.

Remember that if you change any Python code, you will need to restart the development server and re-attach debugger in VS Code.

-Ram Kulkarni

8 Replies to “Remote Debugging Django Project in Docker”

  1. Hi Ram – great video, I have followed it all the way through, but at the end as soon as I click the Debug Play button in Visual Studio Code I get the following: Error Debug adapter process has terminated unexpectedly

    I have tried rerunning things from that start, but every time I get that same message when I press the Debug Play button in Visual Studio Code. Do you know what the issue could be? …thanks and much appreciated.

    1. Did you run Django dev server in the docker container? The command is python manage.py runserver --noreload 0.0.0.0:81. See #4 step in the blog.

  2. Hi, thanks for the reply. That is the command I ran as per your YouTube video. The web page would appear fine at port 81. It is just at the end as soon as I click the Debug Play button in Visual Studio Code I get the following:
    “Error Debug adapter process has terminated unexpectedly”.
    …and there is no debugging available.

    1. If you have followed all the steps as per blog and still not able to debug then I would suggest rebuilding the docker image.

      1. Remove the docker instance. $ docker rm -f django-apache2
      2. Rebuild the image. $ docker-compose build
      3. Start the instance. $ docker-compose up

  3. Hi Ram – thanks for the reply, I have tried rebuilding the project a few times and just done it again now but I still get the error: Error Debug adapter process has terminated unexpectedly.

    1. You may want to check if any other process on the host machine has opened the port that debugger in the docker container is listening to. In the example in the blog post, this port is 3500. You want to make sure that no other process on the host machine has opened 3500 port.

Leave a Reply