name: social-app-prod services: redis: image: redis:7-alpine container_name: social-prod-redis restart: unless-stopped environment: - REDIS_PASSWORD=${SOCIAL_REDIS__PASSWORD} command: > sh -c 'test -n "$$REDIS_PASSWORD" && exec redis-server --appendonly yes --dir /data --requirepass "$$REDIS_PASSWORD" || (echo "REDIS_PASSWORD is required" >&2; exit 1)' volumes: - redis_data:/data healthcheck: test: ["CMD", "sh", "-c", "if [ -n \"$$REDIS_PASSWORD\" ]; then redis-cli -a \"$$REDIS_PASSWORD\" ping; else redis-cli ping; fi"] interval: 5s timeout: 3s retries: 10 litellm: image: ${SOCIAL_BACKEND_IMAGE:-social-app-backend:prod} container_name: social-prod-litellm restart: unless-stopped env_file: - ./.env.prod environment: - PYTHONPATH=/app/backend/src - PYTHONDONTWRITEBYTECODE=1 - SOCIAL_REDIS__HOST=redis - SOCIAL_REDIS__PORT=6379 command: > sh -c '.venv/bin/python backend/scripts/build_litellm_proxy_config.py --output /tmp/litellm-proxy-config.yaml && .venv/bin/litellm --config /tmp/litellm-proxy-config.yaml --host ${SOCIAL_LITELLM__BIND_HOST:-0.0.0.0} --port ${SOCIAL_LITELLM__PORT:-3875}' healthcheck: test: [ "CMD", "python", "-c", "import os,sys,urllib.request;port=os.getenv('SOCIAL_LITELLM__PORT','3875');u=f'http://127.0.0.1:{port}/health';sys.exit(0 if urllib.request.urlopen(u, timeout=3).getcode() < 500 else 1)", ] interval: 15s timeout: 5s retries: 10 web: image: ${SOCIAL_BACKEND_IMAGE:-social-app-backend:prod} container_name: social-prod-web restart: unless-stopped env_file: - ./.env.prod environment: - PYTHONPATH=/app/backend/src - PYTHONDONTWRITEBYTECODE=1 - SOCIAL_RUNTIME__SERVICE_NAME=web - SOCIAL_RUNTIME__ENVIRONMENT=${SOCIAL_RUNTIME__ENVIRONMENT:-prod} - SOCIAL_REDIS__HOST=redis - SOCIAL_REDIS__PORT=6379 - SOCIAL_LITELLM__HOST=litellm - SOCIAL_LITELLM__PORT=${SOCIAL_LITELLM__PORT:-3875} command: > sh -c '.venv/bin/uvicorn app:app --host ${SOCIAL_WEB__HOST:-0.0.0.0} --port ${SOCIAL_WEB__PORT:-5775} --workers ${SOCIAL_WEB__WORKERS:-2} --log-level $(printf "%s" "${SOCIAL_RUNTIME__LOG_LEVEL:-info}" | tr "[:upper:]" "[:lower:]")' ports: - "127.0.0.1:${SOCIAL_WEB__PORT:-5775}:${SOCIAL_WEB__PORT:-5775}" depends_on: redis: condition: service_healthy litellm: condition: service_healthy volumes: - ../logs:/app/logs - ./static/releases:/app/static/releases:ro healthcheck: test: [ "CMD", "python", "-c", "import os,sys,urllib.request;port=os.getenv('SOCIAL_WEB__PORT','5775');u=f'http://127.0.0.1:{port}/health';sys.exit(0 if urllib.request.urlopen(u, timeout=3).getcode() < 500 else 1)", ] interval: 15s timeout: 5s retries: 10 worker-critical: image: ${SOCIAL_BACKEND_IMAGE:-social-app-backend:prod} container_name: social-prod-worker-critical restart: unless-stopped env_file: - ./.env.prod environment: - PYTHONPATH=/app/backend/src - PYTHONDONTWRITEBYTECODE=1 - SOCIAL_RUNTIME__SERVICE_NAME=worker-critical - SOCIAL_RUNTIME__ENVIRONMENT=${SOCIAL_RUNTIME__ENVIRONMENT:-prod} - SOCIAL_REDIS__HOST=redis - SOCIAL_REDIS__PORT=6379 - SOCIAL_LITELLM__HOST=litellm - SOCIAL_LITELLM__PORT=${SOCIAL_LITELLM__PORT:-3875} command: > sh -c '.venv/bin/taskiq worker core.taskiq.app:critical_broker core.agentscope.runtime.tasks --workers ${SOCIAL_WORKER__GROUPS__CRITICAL__CONCURRENCY:-2}' depends_on: redis: condition: service_healthy litellm: condition: service_healthy volumes: - ../logs:/app/logs - ./static/releases:/app/static/releases:ro worker-default: image: ${SOCIAL_BACKEND_IMAGE:-social-app-backend:prod} container_name: social-prod-worker-default restart: unless-stopped env_file: - ./.env.prod environment: - PYTHONPATH=/app/backend/src - PYTHONDONTWRITEBYTECODE=1 - SOCIAL_RUNTIME__SERVICE_NAME=worker-default - SOCIAL_RUNTIME__ENVIRONMENT=${SOCIAL_RUNTIME__ENVIRONMENT:-prod} - SOCIAL_REDIS__HOST=redis - SOCIAL_REDIS__PORT=6379 - SOCIAL_LITELLM__HOST=litellm - SOCIAL_LITELLM__PORT=${SOCIAL_LITELLM__PORT:-3875} command: > sh -c '.venv/bin/taskiq worker core.taskiq.app:default_broker core.agentscope.runtime.tasks --workers ${SOCIAL_WORKER__GROUPS__DEFAULT__CONCURRENCY:-2}' depends_on: redis: condition: service_healthy litellm: condition: service_healthy volumes: - ../logs:/app/logs - ./static/releases:/app/static/releases:ro worker-bulk: image: ${SOCIAL_BACKEND_IMAGE:-social-app-backend:prod} container_name: social-prod-worker-bulk restart: unless-stopped env_file: - ./.env.prod environment: - PYTHONPATH=/app/backend/src - PYTHONDONTWRITEBYTECODE=1 - SOCIAL_RUNTIME__SERVICE_NAME=worker-bulk - SOCIAL_RUNTIME__ENVIRONMENT=${SOCIAL_RUNTIME__ENVIRONMENT:-prod} - SOCIAL_REDIS__HOST=redis - SOCIAL_REDIS__PORT=6379 - SOCIAL_LITELLM__HOST=litellm - SOCIAL_LITELLM__PORT=${SOCIAL_LITELLM__PORT:-3875} command: > sh -c '.venv/bin/taskiq worker core.taskiq.app:bulk_broker core.agentscope.runtime.tasks --workers ${SOCIAL_WORKER__GROUPS__BULK__CONCURRENCY:-1}' depends_on: redis: condition: service_healthy litellm: condition: service_healthy volumes: - ../logs:/app/logs - ./static/releases:/app/static/releases:ro init-job: image: ${SOCIAL_BACKEND_IMAGE:-social-app-backend:prod} container_name: social-prod-init-job restart: "no" env_file: - ./.env.prod environment: - PYTHONPATH=/app/backend/src - PYTHONDONTWRITEBYTECODE=1 - SOCIAL_RUNTIME__SERVICE_NAME=init-job - SOCIAL_RUNTIME__ENVIRONMENT=${SOCIAL_RUNTIME__ENVIRONMENT:-prod} - SOCIAL_REDIS__HOST=redis - SOCIAL_REDIS__PORT=6379 - SOCIAL_LITELLM__HOST=litellm - SOCIAL_LITELLM__PORT=${SOCIAL_LITELLM__PORT:-3875} command: .venv/bin/python -m core.runtime.cli bootstrap depends_on: redis: condition: service_healthy litellm: condition: service_healthy volumes: - ../logs:/app/logs - ./static/releases:/app/static/releases:ro profiles: - job volumes: redis_data: