feat(dev): Enable hot reloading and streamline local development
This commit significantly improves the local development experience by enabling hot reloading for the Django application. This is achieved by installing the project as an editable package within the Docker services.
Key changes:
- **Hot Reloading:**
- Modified `docker-compose.yml` for `web` and `celery` services to use `uv pip install --editable . --no-deps`.
- Mounted the project root (`./`) to `/code` in `web` and `celery` services to facilitate the editable install.
- **Docker & Build Enhancements:**
- Added `uv` binary to stage-1 in the `Dockerfile` for faster package operations.
- Adjusted file permissions in `Dockerfile` during the app copy.
- Set `DEBUG=true` for the `web` service in `docker-compose.yml` for easier local debugging.
- Changed `restart` policy to `unless-stopped` for `web` and `celery` dev services.
- Added a healthcheck for the `redis` service in the dev `docker-compose.yml`.
- **Code & Script Cleanup:**
- Removed the custom `HealthCheckView` from the `home` app, as health checks are now handled by django-health-checks.
- Updated paths and commands in `scripts/entrypoint.sh`, `scripts/prebuild.sh`, and `scripts/reset-db_make-migrations_seed-data.sh` to align with the new setup and remove obsolete steps (e.g., db cache table creation; we now use redis).
This commit is contained in:
parent
02f23dba28
commit
51de3c7a6d
7 changed files with 28 additions and 48 deletions
|
|
@ -86,8 +86,9 @@ EOT
|
|||
# See <https://hynek.me/articles/docker-signals/>.
|
||||
STOPSIGNAL SIGINT
|
||||
|
||||
COPY --from=build --chown=app:app /app /app
|
||||
COPY --from=build --chown=app:app --chmod=u+rw /app /app
|
||||
|
||||
COPY --from=ghcr.io/astral-sh/uv:0.7.2 /uv /app/bin/uv
|
||||
COPY --chown=app:app --chmod=700 /scripts/entrypoint.sh /entrypoint.sh
|
||||
COPY --chown=app:app --chmod=700 /scripts/deploy.sh /deploy.sh
|
||||
COPY --chown=app:app --chmod=700 /manage.py /app/manage.py
|
||||
|
|
|
|||
|
|
@ -1,30 +1,41 @@
|
|||
services:
|
||||
web:
|
||||
build: .
|
||||
#command: ["django-admin", "runserver", "0.0.0.0:8000"]
|
||||
command: bash -c "cd /code && uv pip install --editable . --no-deps && python manage.py runserver 0.0.0.0:8000"
|
||||
ports:
|
||||
- 8000:8000
|
||||
restart: always
|
||||
- "8000:8000"
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- DEBUG=true
|
||||
volumes:
|
||||
- ./seed:/seed:ro
|
||||
# DANGEROUS DUE TO DOCKERFILE PACKAGE BUILDING/INSTALLATION
|
||||
# will need to use editable package instead somehow
|
||||
#- ./src/pkmntrade_club:/app/lib/python3.12/site-packages/pkmntrade_club:ro
|
||||
- ./:/code
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_started
|
||||
celery:
|
||||
build: .
|
||||
command: ["celery", "-A", "pkmntrade_club.django_project", "worker", "-l", "INFO", "-B", "-E"]
|
||||
restart: always
|
||||
command: bash -c "cd /code && uv pip install --editable . --no-deps && celery -A pkmntrade_club.django_project worker -l INFO -B -E"
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./:/code
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_started
|
||||
redis:
|
||||
image: redis:latest
|
||||
restart: always
|
||||
ports:
|
||||
- 6379:6379
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
db:
|
||||
image: postgres:16
|
||||
restart: always
|
||||
|
|
@ -37,6 +48,5 @@ services:
|
|||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
|
|
@ -8,10 +8,8 @@ fi
|
|||
|
||||
/deploy.sh
|
||||
|
||||
# show command version before running it
|
||||
$1 --version
|
||||
|
||||
if [ "$1" == "granian" ]; then
|
||||
granian --version
|
||||
echo "Appending static files path to granian command (requires granian >= 2.3.0)"
|
||||
STATIC_ROOT=$(python -c 'import os; import pkmntrade_club; from django.conf import settings; print(settings.STATIC_ROOT)')
|
||||
set -- "$@" --static-path-mount "$STATIC_ROOT"
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
#!/bin/bash
|
||||
|
||||
cd src/pkmntrade_club/
|
||||
|
||||
# Remove all files in staticfiles except .gitkeep
|
||||
if [ -d "staticfiles" ]; then
|
||||
find staticfiles -type f ! -name '.gitkeep' -delete
|
||||
find staticfiles -type d -empty -delete
|
||||
fi
|
||||
|
||||
# Build the tailwind theme css
|
||||
cd src/pkmntrade_club/theme/static_src
|
||||
cd theme/static_src
|
||||
npm install . && npm run build
|
||||
|
|
@ -9,18 +9,14 @@ source .env
|
|||
set +a
|
||||
uv run manage.py makemigrations --noinput
|
||||
|
||||
echo "Resetting database... "
|
||||
echo "Resetting dev database... "
|
||||
docker compose down \
|
||||
&& docker volume rm -f pkmntradeclub_postgres_data \
|
||||
&& ./scripts/rebuild-and-run.sh
|
||||
|
||||
# Wait for the database to be ready.
|
||||
echo "Waiting 15 seconds for the database to be ready, and migrations to be autorun..."
|
||||
echo "Waiting 15 seconds for migrations to be auto-run..."
|
||||
sleep 15
|
||||
|
||||
echo "Creating cache table..."
|
||||
docker compose exec -it web bash -c "django-admin createcachetable django_cache"
|
||||
|
||||
echo "Loading seed data..."
|
||||
docker compose exec -it web bash -c "django-admin loaddata /seed/0*"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from django.urls import path
|
||||
|
||||
from .views import HomePageView, HealthCheckView
|
||||
from .views import HomePageView
|
||||
|
||||
urlpatterns = [
|
||||
path("", HomePageView.as_view(), name="home"),
|
||||
|
|
|
|||
|
|
@ -139,29 +139,3 @@ class HomePageView(TemplateView):
|
|||
def get(self, request, *args, **kwargs):
|
||||
"""Override get method to add caching"""
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
class HealthCheckView(View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
||||
try:
|
||||
from django.db import connection
|
||||
connection.cursor().execute("SELECT 1")
|
||||
except Exception as e:
|
||||
return HttpResponse("Database connection failed", status=500)
|
||||
|
||||
try:
|
||||
from pkmntrade_club.trades.models import TradeOffer
|
||||
with contextlib.redirect_stdout(None):
|
||||
print(TradeOffer.objects.count())
|
||||
except Exception as e:
|
||||
return HttpResponse("DB models not reachable, but db is reachable", status=500)
|
||||
|
||||
try:
|
||||
from django.core.cache import cache
|
||||
cache.set("test", "test")
|
||||
with contextlib.redirect_stdout(None):
|
||||
print(cache.get("test"))
|
||||
except Exception as e:
|
||||
return HttpResponse("Cache not reachable", status=500)
|
||||
|
||||
return HttpResponse("OK/HEALTHY")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue