Using Github Codespaces for an Efficient Django Development Environment

I ended up writing online store almost from scratch because of product and market restrictions and then stuck with it because price and freedom it provides. Meaning some features like live preview are not available. This was possible thanks to my partner knowing basics of HTML.

With Github Codespaces being released to all developers I though I could use it to spin up development environment with lowest amount of manual steps required.

The project is Django application using PostgreSQL as database and Cloudinary to host images. I'm also using Tailwind UI which comes with CLI to build CSS. Codespaces come with ready made docker-compose.yml and Docker for Python and Node.js development so I didn't have to touch Dockerfile.

I started by putting sensitive ENV variables like mail provider and payment gateway credentials to secrets. Then I used docker-compose.yml to store static non-sensitive variables and containerEnv in devcontainer.json to store dynamic variables like PUBLIC_URL.

.devcontainer/docker-compose.yml

version: '3.8'

services:
  app:
    build:
      context: ..
      dockerfile: .devcontainer/Dockerfile
      args:
        # Update 'VARIANT' to pick a version of Python: 3, 3.10, 3.9, 3.8, 3.7, 3.6
        # Append -bullseye or -buster to pin to an OS version.
        # Use -bullseye variants on local arm64/Apple Silicon.
        VARIANT: 3.10-bullseye
        # Optional Node.js version to install
        NODE_VERSION: '18'

    environment:
      - [email protected]
      - DATABASE_URL=postgres://postgres:postgres@localhost:5432/postgres
      - ECOMAIL_LIST_ID=2

.devcontainer/devcontainer.json

  // Use 'postCreateCommand' to run commands after the container is created.
  "postCreateCommand": "pipenv install --dev && pip install pre-commit && pre-commit install && pipenv run migrate && pipenv run loaddata && npm install",

  // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
  "remoteUser": "vscode",
  "portsAttributes": {
    "8000": {
      "label": "web"
    }
  },

  "containerEnv": {
    "PUBLIC_URL": "https://${localEnv:CODESPACE_NAME}-8000.${localEnv:GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN}",
    "PAYMENT_HOST": "${localEnv:CODESPACE_NAME}-8000.${localEnv:GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN}",
    "PAYMENT_RETURN_HOST": "https://${localEnv:CODESPACE_NAME}-8000.${localEnv:GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN}"
  }

devcontainer.json also contains postCreateCommand that I used to do following steps:

  • install dependencies
  • install pre-commit
  • initialize database
  • load production data from fixtures

I'm using pipenv to manage dependencies and virtual environments. One of features of Pipenv I like are scripts. They provide a way to create alias for complicated or long commands. Most of the commands are Django management commands. The only exception being dev command. This command starts two separate processes using tool called honcho. Honcho is a Python library that makes it easy to run multiple processes in a Unix environment. The processes are defined in Procfile.dev.

Pipfile

...
[scripts]
dev = "honcho -f Procfile.dev start"
test = "python manage.py test"
runserver = "python manage.py runserver"
makemigrations = "python manage.py makemigrations"
migrate = "python manage.py migrate"
loaddata = "python manage.py loaddata categories products pages images"

This way I could use VS Code Tasks to start both Django and CSS minifier.

.vscode/tasks.json

{
  "version": "2.0.0",
  "tasks": [
    {
      "type": "shell",
      "command": "pipenv run dev",
      "problemMatcher": [],
      "label": "Run webserver",
      "detail": ""
    }
  ]
}

In conclusion, I was able to use Github Codespaces to spin up a development environment for my Django application with minimal manual steps. Overall, Github Codespaces proved to be a valuable tool for the project.