Files
headquarter/docker-compose.traefik.yml
T
Fusion ea6c466c6c feat: add automatic database initialization and recovery
- Add init_database() with alembic programmatic API and retry logic
- Add connection retry with exponential backoff (5 attempts)
- Improve error messages for connection/auth failures
- Add table existence check before seeding data
- Update startup event to run migrations before seeding
- Add wait-for-db.sh script for Docker containers
- Update Docker and docker-compose configurations

Quality gates: ruff ✓, mypy ✓, unit tests (8 passed)
2026-05-18 22:10:15 +02:00

127 lines
4.0 KiB
YAML

# Docker Compose for deployment behind an existing Traefik reverse proxy
# All domains and the proxy web name are configurable via environment variables
services:
# PostgreSQL Database
postgres:
image: postgres:15-alpine
container_name: hq-postgres
environment:
POSTGRES_USER: ${POSTGRES_USER:-headquarter}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-headquarter}
POSTGRES_DB: ${POSTGRES_DB:-headquarter}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-headquarter} -d ${POSTGRES_DB:-headquarter}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
networks:
- backend
restart: unless-stopped
# Redis Cache
redis:
image: redis:7-alpine
container_name: hq-redis
command: redis-server --appendonly yes
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
start_period: 5s
networks:
- backend
restart: unless-stopped
# Web Frontend
headquarter-frontend:
build:
context: ./apps/web
dockerfile: Dockerfile
args:
VITE_API_BASE_URL: ${API_PUBLIC_URL:-https://${API_DOMAIN}}
VITE_APP_URL: ${WEB_PUBLIC_URL:-https://${WEB_DOMAIN}}
container_name: hq-web
environment:
VITE_API_BASE_URL: ${API_PUBLIC_URL:-https://${API_DOMAIN}}
VITE_APP_URL: ${WEB_PUBLIC_URL:-https://${WEB_DOMAIN}}
depends_on:
- headquarter-api
networks:
- backend
- traefik
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.headquarter-frontend.rule=Host(`${WEB_DOMAIN}`)"
- "traefik.http.routers.headquarter-frontend.entrypoints=websecure"
- "traefik.http.routers.headquarter-frontend.tls=true"
- "traefik.http.routers.headquarter-frontend.tls.certresolver=${TRAEFIK_CERT_RESOLVER:-letsencrypt}"
- "traefik.http.services.headquarter-frontend.loadbalancer.server.port=80"
# API Service
headquarter-api:
build:
context: ./apps/api
dockerfile: Dockerfile
container_name: hq-api
environment:
APP_ENV: production
DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-headquarter}:${POSTGRES_PASSWORD:-headquarter}@postgres:5432/${POSTGRES_DB:-headquarter}
POSTGRES_HOST: postgres
POSTGRES_PORT: 5432
REDIS_URL: redis://redis:6379/0
JWT_SECRET: ${JWT_SECRET:-change-me-in-production}
REPO_BASE_PATH: /data/repos
API_DOMAIN: ${API_DOMAIN}
WEB_DOMAIN: ${WEB_DOMAIN}
AUTHENTIK_DOMAIN: ${AUTHENTIK_DOMAIN}
API_PUBLIC_URL: ${API_PUBLIC_URL:-}
WEB_PUBLIC_URL: ${WEB_PUBLIC_URL:-}
AUTHENTIK_CLIENT_ID: ${AUTHENTIK_CLIENT_ID:-headquarter-web}
AUTHENTIK_CLIENT_SECRET: ${AUTHENTIK_CLIENT_SECRET}
AUTHENTIK_APPLICATION_SLUG: ${AUTHENTIK_APPLICATION_SLUG:-headquarter-web}
AUTHENTIK_AUTHORIZE_URL: ${AUTHENTIK_AUTHORIZE_URL:-}
AUTHENTIK_TOKEN_URL: ${AUTHENTIK_TOKEN_URL:-}
AUTHENTIK_JWKS_URL: ${AUTHENTIK_JWKS_URL:-}
AUTHENTIK_ISSUER: ${AUTHENTIK_ISSUER:-}
AUTHENTIK_AUDIENCE: ${AUTHENTIK_AUDIENCE:-headquarter-web}
volumes:
- repo_data:/data/repos
- avatar_uploads:/app/uploads
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
networks:
- backend
- traefik
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.headquarter-api.rule=Host(`${API_DOMAIN}`)"
- "traefik.http.routers.headquarter-api.entrypoints=websecure"
- "traefik.http.routers.headquarter-api.tls=true"
- "traefik.http.routers.headquarter-api.tls.certresolver=${TRAEFIK_CERT_RESOLVER:-letsencrypt}"
- "traefik.http.services.headquarter-api.loadbalancer.server.port=8000"
volumes:
postgres_data:
redis_data:
repo_data:
avatar_uploads:
networks:
backend:
driver: bridge
traefik:
external: true
name: ${TRAEFIK_NETWORK:-traefik}