Files
jobtrackingapp/docker-compose.yml
T
cesnimda 824251d328 feat(ai): provider router (ollama|gemini|groq) for heavy CV calls
The structured /cv/* calls funnel through a provider router so production can
offload a weak local GPU (GTX 1060) to a cloud provider without any .NET change.
Default stays "ollama" (keyless/local) and /summarize remains local distilbart.

- AI_PROVIDER=ollama|gemini|groq dispatch inside _ollama_generate_json/_text
  (entry-point names kept, so no call sites change; Ollama path is byte-identical).
- Gemini (x-goog-api-key header, not URL query) and Groq (OpenAI-compatible
  chat/completions) added via stdlib urllib — zero new dependencies.
- /health reports ai_provider + ai_provider_configured.
- Keys read from env only; never logged/committed.
- Compose + .env.example pass AI_PROVIDER/GEMINI_*/GROQ_* through.

Tests: 11 passed (default Ollama unchanged, Gemini/Groq dispatch, missing-key 503,
health reports provider).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 10:40:55 +02:00

126 lines
3.9 KiB
YAML

services:
backend:
build:
context: .
dockerfile: JobTrackerApi/Dockerfile
volumes:
- jobtracker_data:/data
environment:
- ASPNETCORE_URLS=http://+:8080
- Data__Root=/data
- Exports__DailyFolder=/data/exports
- Database__Provider=${DATABASE_PROVIDER:-sqlite}
- ConnectionStrings__JobTracker=${JOBTRACKER_CONNECTION_STRING}
# If you enable HTTPS at a reverse proxy (recommended), handle redirects there.
- HttpsRedirection__Enabled=false
# Authentication (recommended for any non-local deployment)
- Auth__Require=true
- Auth__JwtKey=${AUTH_JWT_KEY}
- Auth__AdminEmail=${AUTH_ADMIN_EMAIL}
- Auth__AdminPassword=${AUTH_ADMIN_PASSWORD}
# Optional: allow Google ID-token bearer auth
- Auth__GoogleClientId=${AUTH_GOOGLE_CLIENT_ID}
- Google__GmailClientSecret=${GOOGLE_GMAIL_CLIENT_SECRET}
- Google__GmailRedirectUri=${GOOGLE_GMAIL_REDIRECT_URI}
- Ai__BaseUrl=${AI_SERVICE_BASE_URL:-http://ai-service:8001}
- Summarizer__BaseUrl=${SUMMARIZER_BASE_URL:-http://ai-service:8001}
# Email (SMTP)
# Build metadata should be resolved before deployment. Examples:
# APP_VERSION=1.0.0
# APP_COMMIT_SHA=abc1234
# APP_BUILD_STAMP=2026-03-22 14:00 UTC
# Do not set literal placeholders like $(git rev-parse --short HEAD) in .env.
- App__PublicBaseUrl=${APP_PUBLIC_BASE_URL}
- App__Version=${APP_VERSION}
- App__CommitSha=${APP_COMMIT_SHA}
- App__BuildStamp=${APP_BUILD_STAMP}
- Email__Enabled=${EMAIL_ENABLED}
- Email__SmtpHost=${EMAIL_SMTP_HOST}
- Email__SmtpPort=${EMAIL_SMTP_PORT}
- Email__SmtpEnableSsl=${EMAIL_SMTP_ENABLE_SSL}
- Email__SmtpTimeoutMs=${EMAIL_SMTP_TIMEOUT_MS}
- Email__SmtpUser=${EMAIL_SMTP_USER}
- Email__SmtpPassword=${EMAIL_SMTP_PASSWORD}
- Email__From=${EMAIL_FROM}
- Email__FromName=${EMAIL_FROM_NAME}
expose:
- "8080"
networks:
- default
- shared_services
restart: unless-stopped
frontend:
build:
context: ./job-tracker-ui
args:
- REACT_APP_GOOGLE_CLIENT_ID=${AUTH_GOOGLE_CLIENT_ID}
# Optional override; default in production is `/api`
- REACT_APP_API_BASE_URL=${REACT_APP_API_BASE_URL}
ports:
- "3000:80"
depends_on:
- backend
networks:
- default
- shared_services
restart: unless-stopped
ai-service:
build:
context: ./tools/summarizer
dockerfile: Dockerfile
environment:
- OLLAMA_BASE_URL=${OLLAMA_BASE_URL:-http://ollama:11434}
- OLLAMA_MODEL=${OLLAMA_MODEL:-qwen2.5:7b}
# AI provider for heavy /cv/* calls: ollama (default) | gemini | groq.
# Set AI_PROVIDER=gemini + GEMINI_API_KEY in prod to offload a weak local GPU.
- AI_PROVIDER=${AI_PROVIDER:-ollama}
- GEMINI_API_KEY=${GEMINI_API_KEY:-}
- GEMINI_MODEL=${GEMINI_MODEL:-gemini-2.0-flash}
- GROQ_API_KEY=${GROQ_API_KEY:-}
- GROQ_MODEL=${GROQ_MODEL:-llama-3.3-70b-versatile}
ports:
- "8001:8001"
depends_on:
- ollama
networks:
- default
- shared_services
restart: unless-stopped
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8001/health', timeout=5).read()"]
interval: 30s
timeout: 10s
retries: 3
ollama:
image: ollama/ollama:latest
ports:
- "11434:11434"
environment:
- OLLAMA_HOST=0.0.0.0:11434
volumes:
- ollama_data:/root/.ollama
networks:
- default
- shared_services
restart: unless-stopped
gpus: all
healthcheck:
test: ["CMD", "ollama", "list"]
interval: 20s
timeout: 15s
retries: 10
start_period: 20s
volumes:
jobtracker_data:
ollama_data:
networks:
shared_services:
external: true
name: jobtracker_shared