Dockerize Django app with dev/beta/prod environment configuration #4

Closed
opened 2026-07-01 12:09:21 -07:00 by westfarn · 0 comments
Owner

Summary

Containerize the company_site Django project so it runs in Docker with environment-specific configuration for dev, beta, and prod. Settings (especially logging and database) should be driven by environment variables rather than hardcoded values or server-local files.

Background / Current State

  • Single company_site/settings.py with hardcoded secrets, SQLite database, and DEBUG = True
  • Production uses a separate local_settings.py on the server (preserved during deploy via scripts/deploy.sh rsync excludes)
  • Deploy workflow (.gitea/workflows/deploy.yml) runs tests then rsyncs to a host venv + systemctl restart company
  • psycopg2-binary and gunicorn already in requirements.txt but Postgres is not wired in settings
  • No Docker or docker-compose files exist yet

Goals

  1. Docker image for the Django app (Gunicorn WSGI)
  2. docker-compose for local dev (app + Postgres service)
  3. Environment levels: dev, beta, prod selectable via env var (e.g. DJANGO_ENV or APP_ENV)
  4. Flexible settings via environment variables for secrets and config that differ per environment
  5. Environment-specific logging (beta vs prod may differ in level, handlers, format, or destinations)
  6. PostgreSQL as the database backend in beta/prod (SQLite acceptable for local dev if desired)

Proposed Approach

Settings refactor

  • Split settings into a base module plus environment overlays, or use a single settings module that reads from env vars
  • Move secrets out of source control: SECRET_KEY, reCAPTCHA keys, SMTP credentials, Tianji config, etc.
  • Use DJANGO_SETTINGS_MODULE or DJANGO_ENV to select dev/beta/prod behavior
  • Database config from env vars:
    • DATABASE_URL or DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD
  • Other env-driven settings: DEBUG, ALLOWED_HOSTS, TIANJI_ENABLED, static/media paths

Logging

  • Define LOGGING dict per environment in settings overlays
  • Dev: verbose console logging, DEBUG level
  • Beta: structured logging, INFO level, possibly file or stdout for container log aggregation
  • Prod: production-appropriate level (WARNING/INFO), no sensitive data in logs, stdout for container runtime

Docker

  • Dockerfile: Python base, install requirements, collectstatic at build or entrypoint, run Gunicorn
  • docker-compose.yml (dev): web service + Postgres + volume for DB persistence
  • .env.example documenting all required variables per environment
  • Entrypoint script: wait for Postgres, run migrations, start Gunicorn

Deployment integration

  • Update .gitea/workflows/deploy.yml and/or scripts/deploy.sh to build and run containers instead of (or alongside) venv + systemd
  • Document how beta and prod differ in env files or compose overrides

Acceptance Criteria

  • docker compose up starts app + Postgres locally with dev settings
  • App connects to Postgres when DATABASE_URL (or equivalent) is set
  • Switching DJANGO_ENV=dev|beta|prod changes DEBUG, logging, and other env-specific behavior
  • No secrets committed to the repo; .env.example lists required vars
  • Beta and prod logging configs are distinct and documented
  • Existing unit tests pass inside the container or CI
  • README or docs cover local dev, beta, and prod Docker usage

Out of Scope (for follow-up tickets)

  • Reverse proxy / TLS termination (nginx, Traefik)
  • Production orchestration (Kubernetes, Swarm)
  • Managed Postgres hosting specifics

Notes

  • Preserve current production behavior during migration; local_settings.py pattern can inform which vars prod needs
  • Consider django-environ or similar for env parsing (optional)
## Summary Containerize the `company_site` Django project so it runs in Docker with environment-specific configuration for **dev**, **beta**, and **prod**. Settings (especially logging and database) should be driven by environment variables rather than hardcoded values or server-local files. ## Background / Current State - Single `company_site/settings.py` with hardcoded secrets, SQLite database, and `DEBUG = True` - Production uses a separate `local_settings.py` on the server (preserved during deploy via `scripts/deploy.sh` rsync excludes) - Deploy workflow (`.gitea/workflows/deploy.yml`) runs tests then rsyncs to a host venv + `systemctl restart company` - `psycopg2-binary` and `gunicorn` already in `requirements.txt` but Postgres is not wired in settings - No Docker or docker-compose files exist yet ## Goals 1. **Docker image** for the Django app (Gunicorn WSGI) 2. **docker-compose** for local dev (app + Postgres service) 3. **Environment levels**: `dev`, `beta`, `prod` selectable via env var (e.g. `DJANGO_ENV` or `APP_ENV`) 4. **Flexible settings** via environment variables for secrets and config that differ per environment 5. **Environment-specific logging** (beta vs prod may differ in level, handlers, format, or destinations) 6. **PostgreSQL** as the database backend in beta/prod (SQLite acceptable for local dev if desired) ## Proposed Approach ### Settings refactor - Split settings into a base module plus environment overlays, or use a single settings module that reads from env vars - Move secrets out of source control: `SECRET_KEY`, reCAPTCHA keys, SMTP credentials, Tianji config, etc. - Use `DJANGO_SETTINGS_MODULE` or `DJANGO_ENV` to select dev/beta/prod behavior - Database config from env vars: - `DATABASE_URL` or `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASSWORD` - Other env-driven settings: `DEBUG`, `ALLOWED_HOSTS`, `TIANJI_ENABLED`, static/media paths ### Logging - Define `LOGGING` dict per environment in settings overlays - **Dev**: verbose console logging, DEBUG level - **Beta**: structured logging, INFO level, possibly file or stdout for container log aggregation - **Prod**: production-appropriate level (WARNING/INFO), no sensitive data in logs, stdout for container runtime ### Docker - `Dockerfile`: Python base, install requirements, collectstatic at build or entrypoint, run Gunicorn - `docker-compose.yml` (dev): web service + Postgres + volume for DB persistence - `.env.example` documenting all required variables per environment - Entrypoint script: wait for Postgres, run migrations, start Gunicorn ### Deployment integration - Update `.gitea/workflows/deploy.yml` and/or `scripts/deploy.sh` to build and run containers instead of (or alongside) venv + systemd - Document how beta and prod differ in env files or compose overrides ## Acceptance Criteria - [ ] `docker compose up` starts app + Postgres locally with dev settings - [ ] App connects to Postgres when `DATABASE_URL` (or equivalent) is set - [ ] Switching `DJANGO_ENV=dev|beta|prod` changes DEBUG, logging, and other env-specific behavior - [ ] No secrets committed to the repo; `.env.example` lists required vars - [ ] Beta and prod logging configs are distinct and documented - [ ] Existing unit tests pass inside the container or CI - [ ] README or docs cover local dev, beta, and prod Docker usage ## Out of Scope (for follow-up tickets) - Reverse proxy / TLS termination (nginx, Traefik) - Production orchestration (Kubernetes, Swarm) - Managed Postgres hosting specifics ## Notes - Preserve current production behavior during migration; `local_settings.py` pattern can inform which vars prod needs - Consider `django-environ` or similar for env parsing (optional)
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ai_ml_operations/company_site#4