services: postgres: image: postgres:17-alpine environment: POSTGRES_DB: ${POSTGRES_DB:-job_queue} POSTGRES_USER: ${POSTGRES_USER:-postgres} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres} ports: - "${POSTGRES_PORT:-5432}:5432" volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-job_queue}"] interval: 5s timeout: 5s retries: 10 backend: image: minimal-job-queue-backend:latest build: context: ./backend command: sh -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000" environment: DEBUG: "true" DJANGO_ALLOWED_HOSTS: localhost,127.0.0.1,0.0.0.0 DJANGO_CORS_ALLOWED_ORIGINS: http://localhost:5173,http://127.0.0.1:5173 POSTGRES_DB: ${POSTGRES_DB:-job_queue} POSTGRES_USER: ${POSTGRES_USER:-postgres} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres} POSTGRES_HOST: postgres POSTGRES_PORT: 5432 JOB_WORKER_MAX_ATTEMPTS_DEFAULT: ${JOB_WORKER_MAX_ATTEMPTS_DEFAULT:-3} JOB_WORKER_LEASE_SECONDS: ${JOB_WORKER_LEASE_SECONDS:-30} JOB_WORKER_BACKOFF_BASE_SECONDS: ${JOB_WORKER_BACKOFF_BASE_SECONDS:-5} JOB_WORKER_BACKOFF_MAX_SECONDS: ${JOB_WORKER_BACKOFF_MAX_SECONDS:-300} ports: - "8000:8000" depends_on: postgres: condition: service_healthy healthcheck: test: [ "CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:8000/api/health/', timeout=2)\"", ] interval: 5s timeout: 5s retries: 20 worker: image: minimal-job-queue-backend:latest pull_policy: never command: python manage.py run_job_workers environment: DEBUG: "false" POSTGRES_DB: ${POSTGRES_DB:-job_queue} POSTGRES_USER: ${POSTGRES_USER:-postgres} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres} POSTGRES_HOST: postgres POSTGRES_PORT: 5432 JOB_WORKER_THREADS: ${JOB_WORKER_THREADS:-4} JOB_WORKER_POLL_INTERVAL_MS: ${JOB_WORKER_POLL_INTERVAL_MS:-500} JOB_WORKER_LEASE_SECONDS: ${JOB_WORKER_LEASE_SECONDS:-30} JOB_WORKER_CLEANUP_INTERVAL_SECONDS: ${JOB_WORKER_CLEANUP_INTERVAL_SECONDS:-5} JOB_WORKER_CLEANUP_BATCH_SIZE: ${JOB_WORKER_CLEANUP_BATCH_SIZE:-100} JOB_WORKER_BACKOFF_BASE_SECONDS: ${JOB_WORKER_BACKOFF_BASE_SECONDS:-5} JOB_WORKER_BACKOFF_MAX_SECONDS: ${JOB_WORKER_BACKOFF_MAX_SECONDS:-300} JOB_WORKER_MAX_ATTEMPTS_DEFAULT: ${JOB_WORKER_MAX_ATTEMPTS_DEFAULT:-3} JOB_WORKER_LOG_LEVEL: ${JOB_WORKER_LOG_LEVEL:-INFO} depends_on: backend: condition: service_healthy frontend: build: context: ./frontend ports: - "5173:80" depends_on: backend: condition: service_healthy volumes: postgres_data: