services: db: image: postgres:16-alpine environment: POSTGRES_USER: ${POSTGRES_USER:-langlearn} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB:-langlearn} volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-langlearn}"] interval: 10s timeout: 5s retries: 10 restart: unless-stopped deploy: resources: limits: cpus: "1" memory: 1G api: build: ./api ports: - "${API_PORT:-8000}:8000" command: sh -c "alembic upgrade head && uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 2" environment: DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-langlearn}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB:-langlearn} ADMIN_USER_EMAILS: ${ADMIN_USER_EMAILS} API_BASE_URL: ${API_BASE_URL} JWT_SECRET: ${JWT_SECRET} ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY} DEEPL_API_KEY: ${DEEPL_API_KEY} DEEPGRAM_API_KEY: ${DEEPGRAM_API_KEY} GEMINI_API_KEY: ${GEMINI_API_KEY} PYTHONPATH: /app STORAGE_PROVIDER: bunny BUNNY_ZONE: ${BUNNY_ZONE} BUNNY_API_KEY: ${BUNNY_API_KEY} BUNNY_CDN_BASE_URL: ${BUNNY_CDN_BASE_URL} BUNNY_TOKEN_AUTH_KEY: ${BUNNY_TOKEN_AUTH_KEY} BUNNY_STORAGE_ENDPOINT: ${BUNNY_STORAGE_ENDPOINT} TRANSACTIONAL_EMAIL_PROVIDER: ${TRANSACTIONAL_EMAIL_PROVIDER} healthcheck: test: [ "CMD-SHELL", 'python -c "import urllib.request; urllib.request.urlopen(''http://localhost:8000/health'')" || exit 1', ] interval: 10s timeout: 5s retries: 10 start_period: 30s depends_on: db: condition: service_healthy restart: unless-stopped deploy: resources: limits: cpus: "1" memory: 1G frontend: build: context: ./frontend args: PUBLIC_API_BASE_URL: ${PUBLIC_API_BASE_URL} ports: - "${FRONTEND_PORT:-3000}:3000" environment: ORIGIN: ${ORIGIN} PUBLIC_API_BASE_URL: ${PUBLIC_API_BASE_URL} PRIVATE_JWT_SECRET: ${JWT_SECRET} PRIVATE_DEEPL_API_KEY: ${DEEPL_API_KEY} depends_on: api: condition: service_healthy restart: unless-stopped deploy: resources: limits: cpus: "0.5" memory: 256M volumes: pgdata: networks: default: name: langlearn