Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add VS Code debug configuration for Docker Compose + Django #188

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d9199ec
Try to get VS Code debugging working with Docker
epicserve Mar 25, 2023
8f1bb43
Create a VS Code Launch Configuration to attach to Django's runserver…
epicserve Mar 28, 2023
5aaeeef
Update Debuggy to run from manage.py
epicserve Mar 31, 2023
60aa072
Install debuggy
epicserve Mar 31, 2023
b88aff2
Change justMyCode setting to false for the debug configuration
epicserve Mar 31, 2023
4908b5f
Add VS Code test configuration
epicserve Mar 31, 2023
33f7d34
Add a Dev Container configuration
epicserve Mar 31, 2023
3c5e6fc
Add VS Code instructions to the README
epicserve Mar 31, 2023
8466610
Ignore the security check because debugpy it only runs in development
epicserve Apr 1, 2023
7c3a737
Add black and isort auto-formatting on save
epicserve Apr 1, 2023
e66bf1c
Add Copilot and docker extensions
epicserve Apr 1, 2023
892a003
Remove the docker extension because it isn't needed inside the container
epicserve Apr 2, 2023
2d1d7a3
No need to override the volume that is in the main docker compose file
epicserve Apr 2, 2023
203c1bf
Make git so it works in a dev container
epicserve Apr 3, 2023
9c858b1
Add links to docs for Microsoft Dev Containers
epicserve Apr 3, 2023
8454fa1
Switch the first stage to 3-bullseye
epicserve Apr 3, 2023
107dde9
Upgrade core dependencies in one step
epicserve Apr 3, 2023
b0fce31
Only install Git if it's the dev environment
epicserve Apr 3, 2023
d28a936
Set bash as the default terminal
epicserve Apr 3, 2023
57f741b
Fix Git not installing
epicserve Apr 4, 2023
de3c3f1
Clean up if statement
epicserve Apr 4, 2023
4a0b136
Make some updates to the readme for VS Code
epicserve Apr 16, 2023
402d2df
Update debugpy logic to not interfere with the PyCharm debugger
epicserve Apr 18, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-docker-compose
{
"name": "Docker Compose Web",

// 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": "web",

// 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": "/srv/app/",

// Prevent the the "Git: fatal: detected dubious ownership in repository" error
"postStartCommand": "git config --global --add safe.directory /srv/app",

"customizations": {
"vscode": {
"extensions": [
"GitHub.copilot",
"ms-python.python",
"ms-python.black-formatter",
"ms-python.isort"
],
"settings": {
"terminal.integrated.defaultProfile.linux": "bash"
}
}
}

// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Uncomment the next line if you want start specific services in your Docker Compose config.
// "runServices": [],

// 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.
// "postCreateCommand": "cat /etc/os-release",

// Configure tool-specific properties.
// "customizations": {},

// Uncomment to connect as an existing user other than the container default. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "devcontainer"
}
26 changes: 26 additions & 0 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: '3.8'
services:
# Update this to the name of the service you want to work with in your docker-compose.yml file
web:
# Uncomment if you want to override the service's Dockerfile to one in the .devcontainer
# folder. Note that the path of the Dockerfile and context is relative to the *primary*
# docker-compose.yml file (the first in the devcontainer.json "dockerComposeFile"
# array). The sample below assumes your primary file is in the root of your project.
#
# build:
# context: .
# dockerfile: .devcontainer/Dockerfile

volumes:
# Update this to wherever you want VS Code to mount the folder of your project
# - ..:/srv/app:cached

# Uncomment the next four lines if you will use a ptrace-based debugger like C++, Go, and Rust.
# cap_add:
# - SYS_PTRACE
# security_opt:
# - seccomp:unconfined

# Overrides default command so things don't shut down after the process ends.
command: /bin/sh -c "while sleep 1000; do :; done"

3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ htmlcov
latest.dump
node_modules
public/static/dist
*.pyc
__pycache__/
.DS_Store
22 changes: 22 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Django Runserver Attach",
"type": "python",
"request": "attach",
"port": 5678,
"host": "localhost",
"justMyCode": false,
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/srv/app"
}
]
}
]
}
18 changes: 18 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"python.testing.pytestArgs": [
"."
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
},
},
"isort.args": [
"--profile",
"black"
],
}
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,32 @@ stop # Stop all docker-compose services
test # Run the Django test runner without coverage
```

## Using VS Code

### Install the required extensions
* Docker
* Dev Containers

### Start Project in a Dev Container
* In a terminal run docker compose with `docker compose up` or run the command "Docker: Compose Up" in VS Code.
* Then run the command "Dev Containers: Attach to Running Container..." and choose the "/web" container

### Debugging Views
* Open the project in a dev container (see above section)
* Set a breakpoint in a Django View
* Go to Run and Debug (CMD+SHIFT+D)
* Click the run icon next to "Django Runserver Attach"
* If you get a prompt that says "Configured debug type 'python' is not supported." Then click "Install python Extension"
and then click the "Install in Dev Container" button.
* In your browser go to the view that has the breakpoint and VS Code should pause at your breakpoint when it's hit.

### Running Tests
* Open the project in a dev container (see above section)
* Hit CMD+SHIFT+P and search for "Testing: Focus on Test Explorer View". If this doesn't show up make sure you install
the python extension in the dev container.
* Find a test and run it.


## Deploying to Production

The Django base site is designed to be production ready because it comes with a production
Expand Down
20 changes: 12 additions & 8 deletions config/docker/Dockerfile.web
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# ------------------------------------------------------------
# STAGE 1: Build Python requirements layer
# ------------------------------------------------------------
FROM python:3-buster as python-requirements
FROM python:3-bullseye as python-requirements

ARG ENV_NAME=dev

Expand All @@ -13,8 +13,7 @@ ENV \
VIRTUAL_ENV=/opt/venv

RUN set -ex \
&& python3 -m venv $VIRTUAL_ENV \
&& $VIRTUAL_ENV/bin/pip install -U setuptools wheel pip
&& python3 -m venv --upgrade-deps $VIRTUAL_ENV

# Install Python packages
COPY config/requirements/${ENV_NAME}_lock.txt ./config/requirements/${ENV_NAME}_lock.txt
Expand All @@ -27,18 +26,19 @@ RUN set -ex \
# ------------------------------------------------------------
# STAGE 2: Dev layer
# ------------------------------------------------------------
FROM python:3-slim-buster as dev
FROM python:3-slim-bullseye as dev

ARG ENV_NAME=dev

# Set the locale
# libxml2-dev is needed for uwsgi in the production stage
# mime-support install (/etc/mime.types) which is needded uWSGI to server static files with the correct mime types
RUN apt-get update \
&& apt-get install -y locales libxml2-dev mime-support \
&& apt-get install -y --no-install-recommends locales libxml2-dev mime-support \
&& echo "LC_ALL=en_US.UTF-8" >> /etc/environment \
&& echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen \
&& echo "LANG=en_US.UTF-8" > /etc/locale.conf \
&& locale-gen en_US.UTF-8 \
&& rm -rf /var/lib/apt/lists/*
&& locale-gen en_US.UTF-8

ENV VIRTUAL_ENV=/opt/venv
ENV LANG=en_US.UTF-8 \
Expand All @@ -51,8 +51,12 @@ ENV LANG=en_US.UTF-8 \

WORKDIR /srv/app

# Only install Git if it's the dev environment
RUN if [ "$ENV_NAME" = "dev" ]; then apt-get install -y --no-install-recommends git; fi \
&& rm -rf /var/lib/apt/lists/*

RUN set -ex \
&& groupadd -r app && useradd --uid=1000 --create-home --home-dir=/home/app --no-log-init -r -g app app \
&& groupadd -r app && useradd --uid=2000 --create-home --home-dir=/home/app --no-log-init -r -g app app \
&& echo "\nsource ./config/bash/bashrc" >> /home/app/.bashrc

COPY --from=python-requirements --chown=app:app $VIRTUAL_ENV $VIRTUAL_ENV
Expand Down
1 change: 1 addition & 0 deletions config/requirements/dev.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
-r prod.in
bandit[toml]
black
debugpy
django-debug-toolbar
django-stubs
django-test-plus
Expand Down
19 changes: 19 additions & 0 deletions config/requirements/dev_lock.txt
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,25 @@ cryptography==40.0.2 \
cssbeautifier==1.14.7 \
--hash=sha256:be7f1ea7a7b009f0172c2c0d0bebb2d136346e786f7182185ea944affb52135a
# via djlint
debugpy==1.6.6 \
--hash=sha256:0ea1011e94416e90fb3598cc3ef5e08b0a4dd6ce6b9b33ccd436c1dffc8cd664 \
--hash=sha256:23363e6d2a04d726bbc1400bd4e9898d54419b36b2cdf7020e3e215e1dcd0f8e \
--hash=sha256:23c29e40e39ad7d869d408ded414f6d46d82f8a93b5857ac3ac1e915893139ca \
--hash=sha256:549ae0cb2d34fc09d1675f9b01942499751d174381b6082279cf19cdb3c47cbe \
--hash=sha256:70ab53918fd907a3ade01909b3ed783287ede362c80c75f41e79596d5ccacd32 \
--hash=sha256:72687b62a54d9d9e3fb85e7a37ea67f0e803aaa31be700e61d2f3742a5683917 \
--hash=sha256:78739f77c58048ec006e2b3eb2e0cd5a06d5f48c915e2fc7911a337354508110 \
--hash=sha256:7aa7e103610e5867d19a7d069e02e72eb2b3045b124d051cfd1538f1d8832d1b \
--hash=sha256:87755e173fcf2ec45f584bb9d61aa7686bb665d861b81faa366d59808bbd3494 \
--hash=sha256:9b5d1b13d7c7bf5d7cf700e33c0b8ddb7baf030fcf502f76fc061ddd9405d16c \
--hash=sha256:a771739902b1ae22a120dbbb6bd91b2cae6696c0e318b5007c5348519a4211c6 \
--hash=sha256:b9c2130e1c632540fbf9c2c88341493797ddf58016e7cba02e311de9b0a96b67 \
--hash=sha256:be596b44448aac14eb3614248c91586e2bc1728e020e82ef3197189aae556115 \
--hash=sha256:c05349890804d846eca32ce0623ab66c06f8800db881af7a876dc073ac1c2225 \
--hash=sha256:de4a045fbf388e120bb6ec66501458d3134f4729faed26ff95de52a754abddb1 \
--hash=sha256:dff595686178b0e75580c24d316aa45a8f4d56e2418063865c114eef651a982e \
--hash=sha256:f6383c29e796203a0bba74a250615ad262c4279d398e89d895a69d3069498305
# via -r config/requirements/dev.in
decorator==5.1.1 \
--hash=sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330 \
--hash=sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186
Expand Down
3 changes: 2 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ services:
target: dev
dockerfile: config/docker/Dockerfile.web

command: sh -c "./manage.py migrate --noinput && ./manage.py runserver 0.0.0.0:8000"
command: sh -c "./manage.py migrate --noinput && /opt/venv/bin/python -Xfrozen_modules=off manage.py runserver 0.0.0.0:8000"

volumes:
- .:/srv/app:cached

ports:
- "8000:8000"
- "5678:5678"

depends_on:
- node
Expand Down
15 changes: 15 additions & 0 deletions manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@
def main() -> None:
"""Run administrative tasks."""
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")

from django.conf import settings

if (
settings.DEBUG
and os.environ.get("PYCHARM_HOSTED") != "1"
and os.environ.get("RUN_MAIN")
or os.environ.get("WERKZEUG_RUN_MAIN")
):
import debugpy

# Use "nosec" inline comment to ignore security check because this doesn't run in production
debugpy.listen(("0.0.0.0", 5678)) # nosec
print("Debugpy attached!")

try:
from django.core.management import execute_from_command_line
except ImportError as exc:
Expand Down