django-with-companions.yaml 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. # process-compose.yaml — Django web app + queue daemon + audit watcher
  2. #
  3. # Pattern: A main HTTP service with two long-running companion daemons
  4. # that depend on the main service being up.
  5. #
  6. # Notes:
  7. # - depends_on ensures startup ordering, not runtime coupling.
  8. # If the web app restarts, the daemons keep running.
  9. # - The audit watcher uses Git Bash for a wrapper script that needs
  10. # coreutils on PATH (single-quoted YAML to escape backslashes).
  11. # - The daemon enforces an OAuth-only policy: ANTHROPIC_API_KEY must
  12. # be unset (handled by the boot-start wrapper).
  13. version: "0.5"
  14. processes:
  15. webapp:
  16. command: "uv run python manage.py serve --host 127.0.0.1 --port 8000 --no-reload"
  17. working_dir: "X:/path/to/myapp"
  18. environment:
  19. - "DJANGO_SETTINGS_MODULE=myapp.settings.local"
  20. - "PYTHONUNBUFFERED=1"
  21. readiness_probe:
  22. http_get:
  23. host: localhost
  24. port: 8000
  25. path: /
  26. initial_delay_seconds: 30 # Django w/ migrations is slow to come up
  27. period_seconds: 15
  28. timeout_seconds: 5
  29. failure_threshold: 3
  30. availability:
  31. restart: always
  32. backoff_seconds: 5
  33. max_restarts: 20
  34. log_location: "logs/webapp.log"
  35. webapp-daemon:
  36. command: "uv run python -m myapp.worker.daemon-start"
  37. working_dir: "X:/path/to/myapp"
  38. environment:
  39. - "PYTHONUNBUFFERED=1"
  40. # NOTE: ANTHROPIC_API_KEY must be UNSET — daemon enforces OAuth-only.
  41. # The boot-start wrapper handles this; for manual runs, unset it first.
  42. depends_on:
  43. webapp:
  44. condition: process_started # Just needs webapp's pid to exist;
  45. # daemon polls webapp itself for readiness
  46. availability:
  47. restart: always
  48. backoff_seconds: 5
  49. max_restarts: 20
  50. shutdown:
  51. signal: 15 # SIGTERM
  52. timeout_seconds: 35 # Allow daemon's 30s graceful shutdown_grace_s
  53. log_location: "logs/webapp-daemon.log"
  54. webapp-feedback:
  55. # Bash wrapper script — paths in single quotes to avoid YAML escape interpretation
  56. command: '"C:/Program Files/Git/usr/bin/bash.exe" --login X:/path/to/myapp/scripts/feedback-wrapper.sh'
  57. working_dir: "X:/path/to/myapp"
  58. environment:
  59. - "PYTHONUNBUFFERED=1"
  60. # Belt-and-braces PATH for the bash wrapper:
  61. - 'PATH=C:\Program Files\Git\usr\bin;C:\Program Files\Git\bin;C:\Users\me\AppData\Local\Programs\Python\Python313\Scripts;C:\Windows\System32'
  62. depends_on:
  63. webapp:
  64. condition: process_started
  65. availability:
  66. restart: always
  67. backoff_seconds: 15
  68. max_restarts: 20
  69. log_location: "logs/webapp-feedback.log"