Unified Django development toolkit for your team using VSCode - Part 1
How to setup a Django project with VSCode dev containers and docker compose

Search for a command to run...
How to setup a Django project with VSCode dev containers and docker compose

No comments yet. Be the first to comment.
Introduction Django-Syzygy is a Django companion that makes database migrations safer in real production environments. It focuses on one specific, painful problem: migrations that are technically valid, but unsafe during rolling deployments. Syzygy w...

Master the core building blocks of Kafka, including partitions, consumer groups, and how to handle tricky topic migrations.

Avoiding Downtime in Django Migrations with django-migration-linter Deploying Django apps with zero downtime is essential in modern production systems, especially when rolling out updates on Kubernetes or deploying worker-based systems incrementally....

Building beautiful, responsive forms in Django doesn’t have to be a painful experience. By combining the power of django-tailwind with django-widget-tweaks and a few well-crafted custom CSS classes, you can create stunning, consistent forms that look...

What is HTMX? HTMX is a powerful tool that allows developers to create highly interactive and dynamic user interfaces without the need for heavy JavaScript frameworks. At its core, HTMX uses HTML attributes to define behaviour, making it an ideal com...

docker compose up -d is amazing right?
You don't know what is does? In simple words it will create required services to make a specific project up and running.
I will not cover basic knowledge about docker and docker compose, there are plenty of tutorials/videos doing deep introduction for this.
We will have a VSCode + Docker compose setup which will run the project in VSCode dev containers, this will make sure that all services are up and running (DB, Django's runserver, Cache ...) We will also setup useful VSCode extensions which will boost productivity and will be available for anyone using the project with VSCode.
Windows (Docker Desktop + VSCode Dev Containers extension)
// Mac M1/M2 users please use Apple Silicon version for Docker Desktop and VSCode for a better performance
What about the time spent by your team or team members on that and specially when using different OS (Mac, Linux, Windows)?
What about opening VSCode (No terminal is needed) and then everything is setup for you out of the box, you will only need git, docker/docker desktop and that's all !
This will also keep your machine clean from different dependencies, you don't have to switch between dependencies version or system packages version, Dockerize everything!
For a full documentation on setting up dev containers please check this official link. I will later on refer to some section to it.
We will start by cloning a dummy Django project which don't do much and try to add Dockerfile, docker-compose.yml and dev container setup to it.
git clone --branch initial_project_setup https://github.com/MounirMesselmeni/django-vscode-dev-containers.git
This a simple Django project containing the required setup with Dockerfile and docker-compose.yml, we use postgres image for database

Dockerfile
FROM python:3.10
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV LC_ALL=C.UTF-8
WORKDIR /app
COPY requirements.txt /app/
RUN pip install -r requirements.txt
docker-compose.yml
version: "3.9"
services:
django:
build:
context: .
dockerfile: ./Dockerfile
command: python manage.py runserver 0.0.0.0:8000
ports:
- 8000:8000
volumes:
- .:/app:cached
depends_on:
- postgres
postgres:
image: postgres:15.0-alpine
user: postgres
environment:
- POSTGRES_USER=app
- POSTGRES_PASSWORD=app
- POSTGRES_DB=app
volumes:
# with named volume we will persist database state E.g after restarting docker/machine
- postgres-data:/var/lib/postgresql/data
restart: unless-stopped
volumes:
postgres-data:
Add a .env file under django_vscode_dev_containers folder
DEBUG=yes
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY=django-insecure-qk0&tbbj(&c9x^t6wu6wkwwg@xox^t0*@(dbo3et03x*+1-avy
ALLOWED_HOSTS=localhost,127.0.0.1,::1,0.0.0.0
DATABASE_URL=psql://app:app@postgres:5432/app
We can do that using VSCode command palette and dev containers extension helper but for the sake of simplicity we will do this by hand.
Create a .devcontainer/devcontainer.json file in the main directory
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/docker-existing-docker-compose
// If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml.
{
"name": "Django VSCode Dev Containers",
// Update the 'dockerComposeFile' list if you have more compose files or use different names.
// The .devcontainer/docker-compose.yml file contains any overrides you need/want to make.
"dockerComposeFile": [
"../docker-compose.yml",
"docker-compose.yml"
],
// The 'service' property is the name of the service for the container that VS Code should
// use. Update this value and .devcontainer/docker-compose.yml to the real service name.
"service": "django",
// The optional 'workspaceFolder' property is the path VS Code should open by default when
// connected. This is typically a file mount in .devcontainer/docker-compose.yml
"workspaceFolder": "/app",
"runServices": [
"django",
"postgres"
]
// Uncomment the next line if you want to keep your containers running after VS Code shuts down.
// "shutdownAction": "none",
// Uncomment the next line to run commands after the container is created - for example installing curl.
// "postCreateCommand": "apt-get update && apt-get install -y curl",
// Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
// "remoteUser": "vscode"
}
Note on runServices, we define here which services we want VSCode to make sure they are up and running, we could have a redis service which we don't need, or it's essential to the proper functioning of the application so we would like VSCode to take care of running it with docker/docker-compose.
And devcontainers/docker-compose.yml
version: '3.9'
services:
# Update this to the name of the service you want to work with in your docker-compose.yml file
django:
# If you want add a non-root user to your Dockerfile, you can use the "remoteUser"
# property in devcontainer.json to cause VS Code its sub-processes (terminals, tasks,
# debugging) to execute as the user. Uncomment the next line if you want the entire
# container to run as this user instead. Note that, on Linux, you may need to
# ensure the UID and GID of the container user you create matches your local user.
# See https://aka.ms/vscode-remote/containers/non-root for details.
#
# user: vscode
# Overrides default command so things don't shut down after the process ends.
command: /bin/sh -c "while sleep 1000; do :; done"
Open the Command Palette (Ctrl/Cmd+shift+p) and search for Rebuild and reopen in Container

Now VSCode will open the project inside the container, we can see the docker building command and output by clicking on Starting Dev container show logs

The logs would look like this

We know that we are developing inside a container in the bottom left corner we can see the name we provided in devcontainer.json file

Now we need more productivity by setting up proper python extensions to use code completion etc with Pylance.
Let's add required extensions list into the .devcontainers/devcontainer.json and some custom vscode setting (Yes you can define VSCode settings in dev container and share them with others)
"settings": {
"python.terminal.activateEnvironment": false,
"python.terminal.activateEnvInCurrentTerminal": true,
"python.pythonPath": "/usr/local/bin/python",
"python.defaultInterpreterPath": "/usr/local/bin/python",
"python.languageServer": "Pylance",
// file formatting options
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
// files to exclude from all checks
"files.exclude": {
"**/*.pyc": true,
"**/.git": false,
"**/migrations/*": false
},
"python.analysis.extraPaths": [
"/usr/local/lib/python3.10/site-packages/"
],
"python.analysis.useImportHeuristic": true,
"python.analysis.autoSearchPaths": true
},
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"aaron-bond.better-comments",
"visualstudioexptteam.vscodeintellicode",
"mikestead.dotenv"
]
Command Palette and search for Rebuild to rebuilt the container and restart:

Now we can see VSCode is installing the extensions inside the dev container

A common problem to this, that sometime Pylance does not work properly from the first time and you need to restart or rebuild, and everytime you add a requirement or change dockerfile VSCode will re-install all the extensions. To fix this we can avoid VSCode extensions reinstalls by adding a persisted volume for those extensions.
Let's modify our Dockerfile to create required extensions folder
FROM python:3.10
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV LC_ALL=C.UTF-8
# Yes we are using the root user now, it's not encouraged but this is only for demo purposes
RUN mkdir -p /root/.vscode-server/extensions /root/.vscode-server-insiders/extensions
WORKDIR /app
COPY requirements.txt /app/
RUN pip install -r requirements.txt
And add the new docker volume in the .devcontainer/docker-compose.yml
version: '3.9'
services:
# Update this to the name of the service you want to work with in your docker-compose.yml file
django:
# If you want add a non-root user to your Dockerfile, you can use the "remoteUser"
# property in devcontainer.json to cause VS Code its sub-processes (terminals, tasks,
# debugging) to execute as the user. Uncomment the next line if you want the entire
# container to run as this user instead. Note that, on Linux, you may need to
# ensure the UID and GID of the container user you create matches your local user.
# See https://aka.ms/vscode-remote/containers/non-root for details.
#
# user: vscode
# Overrides default command so things don't shut down after the process ends.
command: /bin/sh -c "while sleep 1000; do :; done"
volumes:
- vscode_extensions:/root/.vscode-server/extensions
volumes:
vscode_extensions:
Now rebuild again using commands palette

We can re-run Rebuild without Cache just to test out if the extensions changes are working properly

Now we don't re-install extensions as they are persisted in the docker volume

We should be able now to have autocompletion working and navigating/going to third party packages like environ in settings.py with Cmd/Ctrl click


To go inside the container (Our case the django/python one) you click in the + button as shown bellow


We can run our runserver from there
./manage.py runserver 0:8000
And access localhost:8000

Nice what do you think?
This might looks like a lot of work, but you will set it up once and after it's mostly copy paste and you have your environment easy to work with your colleagues/teammates and simplify the process.
Final result could be find in the github repo: