services: pyrunner: build: . container_name: pyrunner ports: - "${PORT:-8000}:8000" volumes: # Persist database and environments - pyrunner_data:/app/data # Uploaded plugins live here so they survive redeploys. Empty on a fresh # install. - pyrunner_plugins:/app/plugins environment: # Required - container will fail to start if not set. # Generate with the commands shown in .env.example - ENCRYPTION_KEY=${ENCRYPTION_KEY:-} # Django settings - SECRET_KEY is also required (no default) - SECRET_KEY=${SECRET_KEY:-} - DEBUG=${DEBUG:-False} # When DEBUG=False, settings.py enables SECURE_SSL_REDIRECT by default, # which would 301 http->https and break a plain-http local/proxied run. # Default it off here (edge/proxy terminates TLS, as on Coolify). - SECURE_SSL_REDIRECT=${SECURE_SSL_REDIRECT:-False} # Secure cookies require HTTPS. Default True (prod / edge-TLS); set False # for a plain-http run or the session cookie won't come back (logout loop). - SESSION_COOKIE_SECURE=${SESSION_COOKIE_SECURE:-True} - CSRF_COOKIE_SECURE=${CSRF_COOKIE_SECURE:-True} - ALLOWED_HOSTS=${ALLOWED_HOSTS:-localhost,127.0.0.1} # Email settings (optional) - EMAIL_BACKEND=${EMAIL_BACKEND:-django.core.mail.backends.console.EmailBackend} - DEFAULT_FROM_EMAIL=${DEFAULT_FROM_EMAIL:-noreply@pyrunner.local} - RESEND_API_KEY=${RESEND_API_KEY:-} - USE_RESEND=${USE_RESEND:-False} # Worker settings - Q_WORKERS=${Q_WORKERS:-2} # Cache: DatabaseCache by default (no extra service). Set REDIS_URL to use # Redis instead — recommended when scaling to many workers/hosts. - REDIS_URL=${REDIS_URL:-} # Gunicorn settings - PORT=8000 # Display-only: the host-published port, used by entrypoint.sh's "Open # http://localhost:..." banner so it matches the real mapping (PORT above # is the fixed container-internal bind, not what you reach from the host). - PUBLIC_PORT=${PORT:-8000} - GUNICORN_WORKERS=${GUNICORN_WORKERS:-2} - GUNICORN_THREADS=${GUNICORN_THREADS:-4} - GUNICORN_TIMEOUT=${GUNICORN_TIMEOUT:-120} restart: unless-stopped healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/')"] interval: 30s timeout: 10s retries: 3 start_period: 60s volumes: pyrunner_data: driver: local pyrunner_plugins: driver: local