• Shopping Cart Shopping Cart
    0Shopping Cart
London App Developer
  • Courses
  • Consulting
  • Tutorials
  • About
  • Click to open the search input field Click to open the search input field Search
  • Menu Menu
Django, Docker, Productivity, VSCode

Debugging a Dockerized Django app with VSCode

I am a huge advocate for integrating Docker into your development process.

There are many benefits to this, such as:

  • Consistent developer environments
  • Parity of development and production environments
  • Dependency isolation from your laptop and development environment

However, all these benefits don’t come without a downside…

When you isolate your development server into a Docker container, your IDE no longer has direct access to the Python runtime on your machine.

This can limit the features your IDE offers and make it difficult to do things such as set breakpoints to debug your code.

However, there is a solution.

VSCode integrates very nicely with Docker and Django, giving you the best of both worlds.

In this guide, I’ll show you how to use VSCode to setup a new Django project that you can run and debug using Docker.

In this guide I’ll show you how to setup a Django project with VSCode and configure it to work with the debugger.

You can find the completed source code for the project we create here: github.com/LondonAppDeveloper/vscode-django-docker

Prerequisites

Before you get started, ensure you have the following:

  • Docker Desktop (or docker and docker-compose if you’re using Linux)
  • Visual Studio Code
  • The Docker and Python VSCode extensions

Creating a Django project

Start by creating a new directory for your project (eg: vscode-django-docker), and open it in VSCode.

Then, add a .gitignore for Python (I use the Python.gitignore template provided by GitHub) and a README.md file.

Screenshot of a new project in VSCode
VSCode new project

Create a new directory called app/ in the root of your project (this is where we’ll store our Django app).

Screenshot of the app directory in our VSCode project
VSCode project with app/ directory

Now we’ll create our Django project by running the command below in the Terminal (macOS/Linux) or PowerShell on Windows:

docker run -v ${PWD}/app:/app -w /app python:3.9-alpine sh -c "pip install Django==3.2 && django-admin startproject app ."

I’ll break this command down and explain what each part does below:

  • docker run is the command for running a docker container.
  • -v ${PWD}/app:/app maps a volume from the app/ directory in our project to the /app directory in the Docker container. We need this so that our Django project files end up on our local filesystem when we run the startproject command. The ${PWD} part is a command that prints the working directory, because the docker run command requires a full path to the directory.
  • -w /app tells the docker container to work from the /app directory which we mapped in the step above.
  • python:3.9-alpine is the Docker image we are using (it’s available on the Docker Hub).
  • sh -c is the start of the command which we will run inside our Docker image. Whatever we pass in after this bit will be executed as a shell command.
  • pip install Django==3.2 will install Django version 3.2 inside the Docker container when it starts.
  • && is for running multiple shell commands on one line.
  • django-admin startproject app . is the Django CLI command for starting a new project. We’re calling the project app, and providing the . character so the project is created in our current directory (otherwise it will add a new subdirectory at app/app/).

When you run this, Docker will download the python:3.9-alpine image (if it’s not cached) and run the commands for installing Django and creating a project.

Screenshot of the Terminal creating a Django project using a single Docker command.
Terminal window when creating a Django project

Once done, you should see the project files appear inside app/:

Creating Docker configs with VSCode

VSCode comes with a very useful tool for auto generating Docker templates for Django.

Before you continue, note that this process will create the following files in your project, replacing them if they already exist:

  • requirements.txt
  • Dockerfile
  • docker-compose.yml
  • docker-compose.debug.yaml
  • .vscode/launch.json
  • .vscode/tasks.json

If you’re following these steps for a project that already has these files, I recommend the process below:

  1. Re-name of move your existing files out of your project (for example, you might rename requirements.txt to requirements.txt.backup).
  2. Run the steps defined below.
  3. Manually update each auto-generated file with the necessary changes from your previous version.
  4. Remove the .backup files.

To use it, you’ll need to access the command pallet using the following shortcut:

  • macOS: CMD + SHIFT + P
  • Windows: CTRL + SHIFT + P

Start typing “add docker” and then choose Docker: Add Docker Files to Workspace.

Screenshot of command pallet with "Add Docker Files to Workspace" highlighted
Command pallet with “Add Docker Files to Workspace” highlighted

On the Select Application Platform prompt, locate Python: Django and select it:

Screenshot of VSCode showing Select Application Platform with Python: Django selected.
VSCode showing Select Application Platform with Python: Django selected.

On the Choose the app’s entry point prompt, select app/manage.py and select it:

Screenshot of the choose apps' entry point
Choose app’s entry point prompt

You should be asked which port your app will listen on. Leave it as 8000 and hit enter:

Port 8000 on port selection page

In the Include optional Docker Compose files? prompt, select Yes:

The following files (displayed in green) should be added to your project:

Modify VSCode Template Files

The template files generated by VSCode are a great start, however in most cases you will need to modify it for your bespoke project.

Note to macOS and Linux users

Because the VSCode devs probably generated these templates using Windows, you’ll need to modify the line endings from CLRF to LF. This needs to be done per file.

To do this, open the file, and select CLRF (bottom right) and choose LF:

Screenshot of VSCode changing CLRF to LF
Changing CLRF to LF

Next we’ll go through each file and make the appropriate changes.

requirements.txt

Update the requirements.txt file to look like this:

django>=3.2,<3.3
gunicorn>=20.0.4,<20.1

(Diff on GitHub)

This will do two things:

  1. Update Django to use 3.2 instead of 3.1 which was auto generated at the time of writing this
  2. Use >= and < syntax to ensure patch versions are auto updated when building the containers

Dockerfile

Next we need to update the Dockerfile.

Where possible, I suggest using alpine based images because they are more lightweight, so I’ll be doing that also.

Update your Dockerfile to read the following:

# For more information, please refer to https://aka.ms/vscode-docker-python
FROM python:3.9-alpine3.13

EXPOSE 8000

# Keeps Python from generating .pyc files in the container
ENV PYTHONDONTWRITEBYTECODE=1

# Turns off buffering for easier container logging
ENV PYTHONUNBUFFERED=1

# Install pip requirements
COPY requirements.txt .
RUN python -m pip install -r requirements.txt

WORKDIR /app
COPY /app /app

# Creates a non-root user with an explicit UID and adds permission to access the /app folder
# For more info, please refer to https://aka.ms/vscode-docker-python-configure-containers
RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
USER appuser

# During debugging, this entry point will be overridden. For more information, please refer to https://aka.ms/vscode-docker-python-debug
# File wsgi.py was not found in subfolder: 'vscode-django-docker'. Please enter the Python path to wsgi file.
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app.wsgi"]

(Diff on GitHub)

Here is a summary of the changes:

  • Changed base image to python:3.9-alpine3.13 because it is more lightweight.
  • Changed the COPY . /app command to COPY /app /app so only our Django app is copied into the Docker image.
  • Modified the gunicorn command to use the app.wsgi file for running our app.

Once these changes are made, you can test them by running the following in the Terminal or Command Prompt window:

docker-compose build
docker-compose up

This will build and run the Docker container using Docker Compose.

Once complete, you should be able to view your Django app by visiting http://127.0.0.1:8000 in your favourite browser:

Gif of starting Django app with docker and testing in browser
Starting docker app and viewing in browser

docker-compose.debug.yml

Open up docker-compose.debug.yml.

Locate the app/manage.py line and remove the app/ to change it to manage.py.

Once done, the full line should look like this:

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"]

The full docker-compose.debug.yml file should look like this:

version: '3.4'

services:
  vscodedjangodocker:
    image: vscodedjangodocker
    build:
      context: .
      dockerfile: ./Dockerfile
    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

(Diff on GitHub)

We make this change because our container is already working from the app/ directory, so we can call the manage.py file directly.

.vscode/launch.json

Next open up .vscode/launch.json, locate the line "localRoot": "${workspaceFolder}", and replace it with "localRoot": "${workspaceFolder}/app",.

The full file should look like this:

{
    "configurations": [
        {
            "name": "Docker: Python - Django",
            "type": "docker",
            "request": "launch",
            "preLaunchTask": "docker-run: debug",
            "python": {
                "pathMappings": [
                    {
                        "localRoot": "${workspaceFolder}/app",
                        "remoteRoot": "/app"
                    }
                ],
                "projectType": "django"
            }
        }
    ]
}

(Diff on GitHub)

Again, this change is because our Django project is going to be stored within /app instead of the root project.

.vscode/tasks.json

Open up .vscode/tasks.json and change "file": "app/manage.py" to "file": "manage.py".

The full file should look like this:

{
	"version": "2.0.0",
	"tasks": [
		{
			"type": "docker-build",
			"label": "docker-build",
			"platform": "python",
			"dockerBuild": {
				"tag": "vscodedjangodocker:latest",
				"dockerfile": "${workspaceFolder}/Dockerfile",
				"context": "${workspaceFolder}",
				"pull": true
			}
		},
		{
			"type": "docker-run",
			"label": "docker-run: debug",
			"dependsOn": [
				"docker-build"
			],
			"python": {
				"args": [
					"runserver",
					"0.0.0.0:8000",
					"--nothreading",
					"--noreload"
				],
				"file": "manage.py"
			}
		}
	]
}

(Diff on GitHub)

Creating a Django View

Now we have updated the files, we’ll create a new Django view that we can use for debugging.

Create a new file at app/app/views.py and fill it with the following contents:

from django.http import HttpResponse


def index(request):
    return HttpResponse('Hello World!')

Then modify app/app/urls.py to read the following:

from django.contrib import admin
from django.urls import path

from app.views import index

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', index),
]

(Diff on GitHub)

Using the Debugger

Finally, let’s test our debugger.

Open up app/app/views.py and add a breakpoint on the return line by clicking the area left of the line number:

Gif of clicking on the breakpoint option on the return line
Select breakpoint

Now start the debugger by selecting Run > Start Debugging:

Screenshot of Start Bugging option under Run.
Run – Start Debugging

The debugger should kick in.

You can select the bug icon on the left to inspect variables:

Screenshot of debugger running in VSCode
Debugger running in VSCode

You can inspect variables from the debugger menu on the left:

Screenshot of the variables section in the debugger
Variables section in the debugger

Use the debugger menu on the top to navigate through the code:

Screenshot of the debugger menu.
VSCode debugger menu

That’s how to use the VSCode interactive debugger with a Django application.

You can find the final source code here: github.com/LondonAppDeveloper/vscode-django-docker

Thank you for reading.

If you have any feedback or comments, or if you prefer to use VSCode a different way, then please leave a comment below.

Tags: Docker, Python, vscode
Share this entry
  • Share on Facebook
  • Share on X
  • Share on WhatsApp
  • Share on Pinterest
  • Share on LinkedIn
  • Share on Tumblr
  • Share on Vk
  • Share on Reddit
  • Share by Mail
https://i0.wp.com/londonappdeveloper.com/wp-content/uploads/2021/04/Artboard-3.png?fit=606%2C474&ssl=1 474 606 mark https://londonappdeveloper.com/wp-content/uploads/2018/12/lon_website_logo-300x110.png mark2021-04-26 14:12:372021-04-26 14:12:39Debugging a Dockerized Django app with VSCode
You might also like
Beginner’s Guide to Python – Lesson 9 – Virtual Environments Beginner’s Guide to Python – Lesson 09 – Virtual Environments
Django and Docker compose logos on a blueish green background Deploying Django with Docker Compose
Setting up PostgreSQL database with a Django Docker application
Introduction to the Python Debugger Tool Introduction to the Python Debugger Tool
Docker and VSCode logos on an orange background Use Docker to create a new Django project in one line
Django Docker Deployment with HTTPS using Letsencrypt
Docker compose and Docker logos on a thumbnail Docker vs Docker Compose, what’s the difference?
Beginner's Guide to Python - Lesson 05 - While Loops Beginner’s Guide to Python – Lesson 05 – While Loops
7 replies
  1. Aizaz
    Aizaz says:
    June 18, 2021 at 8:17 pm

    If my application name is my_app and my root folder is src then what changes do i need to make? I tried replacing app to src everywhere but because you project name is app as well, it creates a lot of confusion. Basically i am trying to debug an existing project

    Reply
  2. dave
    dave says:
    October 31, 2021 at 7:41 pm

    How do you add postgres to this when debugging and other services and how would you add a generalized docker-compose for people to run on server?

    Reply
  3. Ulises
    Ulises says:
    November 18, 2021 at 4:26 am

    This is not works when you have your postgress database running in another containers, even when you are using the same bridge network.

    I do something simple, just modifying the manager.py file in order to listen the debugpy there and open the port which debugpy will use.

    Reply
  4. Pete
    Pete says:
    April 18, 2022 at 7:42 pm

    I had a timeout issue when trying to debug on a linux OS. Temporarily disabling ufw firewall solved this as a quick fix, then I added a ufw firewall rule for this. Thanks for this blog 🙂

    Reply
  5. Cesar
    Cesar says:
    October 15, 2022 at 1:41 am

    Hi, what happend with the python interpreter? how can I configure for working on docker?
    Thx

    Reply
  6. Anonymous
    Anonymous says:
    December 10, 2022 at 9:50 am

    Great article!!
    Some issue happened in excuting “docker run -v ${PWD}/app:/app -w /app python:3.9-alpine sh -c “pip install Django==3.2 && django-admin startproject app .” ” on windows.
    I replace “${PWD}” with “%cd%” and solve the issue

    Reply
  7. chao ju
    chao ju says:
    December 10, 2022 at 9:50 am

    Great article!!
    Some issue happened in excuting “docker run -v ${PWD}/app:/app -w /app python:3.9-alpine sh -c “pip install Django==3.2 && django-admin startproject app .” ” on windows.
    I replace “${PWD}” with “%cd%” and solve the issue

    Reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Pages

  • About
  • Consulting
  • Home
  • Tutorials

Categories

  • AI
  • Android
  • Android Studio
  • Angular
  • Aptana Studio
  • AWS
  • Bootstrap
  • Career advice
  • Celery
  • Databases
  • Deployment
  • DevOps
  • Django
  • Django REST Framework
  • Docker
  • Eclipse
  • Getting Help
  • Git
  • Git Bash
  • Git Flow
  • GitHub Actions
  • Google App Engine
  • IDE
  • Ionic Framework
  • iOS
  • JavaScript
  • Job Search
  • Links
  • Linux
  • Mac OS X
  • macOS
  • Node.JS
  • OpenAI
  • PGAdmin
  • Postgres
  • Productivity
  • Python
  • React
  • Salt Stack
  • Stack Overflow
  • Tools
  • Travis-CI
  • Tutorials
  • Ubuntu
  • Uncategorized
  • Vagrant
  • VSCode
  • WebSockets
  • Windows 10
  • WordPress

London App Developer Ltd,

71-75 Shelton Street, Covent Garden, London, United Kingdom, WC2H 9JQ

Company registration number: 09718346

© London App Developer - London App Developer Ltd, Company Registration Number: 09718346, VAT: GB224061842
  • Link to X
  • Link to Youtube
  • Link to Facebook
  • Link to Reddit
Link to: How to use GitHub Actions Link to: How to use GitHub Actions How to use GitHub Actions Link to: Use Docker to create a new Django project in one line Link to: Use Docker to create a new Django project in one line Docker and VSCode logos on an orange backgroundUse Docker to create a new Django project in one line
Scroll to top Scroll to top Scroll to top

This site uses cookies. By continuing to browse the site, you are agreeing to our use of cookies.

OKLearn more

Cookie and Privacy Settings



How we use cookies

We may request cookies to be set on your device. We use cookies to let us know when you visit our websites, how you interact with us, to enrich your user experience, and to customize your relationship with our website.

Click on the different category headings to find out more. You can also change some of your preferences. Note that blocking some types of cookies may impact your experience on our websites and the services we are able to offer.

Essential Website Cookies

These cookies are strictly necessary to provide you with services available through our website and to use some of its features.

Because these cookies are strictly necessary to deliver the website, refusing them will have impact how our site functions. You always can block or delete cookies by changing your browser settings and force blocking all cookies on this website. But this will always prompt you to accept/refuse cookies when revisiting our site.

We fully respect if you want to refuse cookies but to avoid asking you again and again kindly allow us to store a cookie for that. You are free to opt out any time or opt in for other cookies to get a better experience. If you refuse cookies we will remove all set cookies in our domain.

We provide you with a list of stored cookies on your computer in our domain so you can check what we stored. Due to security reasons we are not able to show or modify cookies from other domains. You can check these in your browser security settings.

Google Analytics Cookies

These cookies collect information that is used either in aggregate form to help us understand how our website is being used or how effective our marketing campaigns are, or to help us customize our website and application for you in order to enhance your experience.

If you do not want that we track your visit to our site you can disable tracking in your browser here:

Other external services

We also use different external services like Google Webfonts, Google Maps, and external Video providers. Since these providers may collect personal data like your IP address we allow you to block them here. Please be aware that this might heavily reduce the functionality and appearance of our site. Changes will take effect once you reload the page.

Google Webfont Settings:

Google Map Settings:

Google reCaptcha Settings:

Vimeo and Youtube video embeds:

Other cookies

The following cookies are also needed - You can choose if you want to allow them:

Privacy Policy

You can read about our cookies and privacy settings in detail on our Privacy Policy Page.

Privacy Policy
Accept settingsHide notification only