# docker-compose.traefik.yml - Production configuration for external Traefik version: '3.8' services: backend: image: picpeak-backend:latest build: context: ./backend dockerfile: Dockerfile restart: unless-stopped depends_on: - db environment: - NODE_ENV=production - PORT=3000 - JWT_SECRET=${JWT_SECRET} - ADMIN_URL=https://picpeak.nothaft.cloud - FRONTEND_URL=https://picpeak.nothaft.cloud # Database - DATABASE_CLIENT=pg - DB_HOST=db - DB_PORT=5432 - DB_USER=${DB_USER:-picpeak} - DB_PASSWORD=${DB_PASSWORD} - DB_NAME=${DB_NAME:-picpeak} # Email - SMTP_HOST=${SMTP_HOST} - SMTP_PORT=${SMTP_PORT} - SMTP_SECURE=${SMTP_SECURE} - SMTP_USER=${SMTP_USER} - SMTP_PASS=${SMTP_PASS} - EMAIL_FROM=${EMAIL_FROM} # Analytics - UMAMI_URL=${UMAMI_URL} - UMAMI_WEBSITE_ID=${UMAMI_WEBSITE_ID} # Storage paths - STORAGE_PATH=/app/storage - EVENTS_PATH=/app/storage/events - ARCHIVE_PATH=/app/storage/events/archived volumes: - ./storage:/app/storage - ./data:/app/data - ./logs:/app/logs networks: - picpeak - traefik labels: - "traefik.enable=true" - "traefik.docker.network=traefik" # Backend API routing - "traefik.http.routers.picpeak-backend.rule=Host(`picpeak.nothaft.cloud`) && PathPrefix(`/api`)" - "traefik.http.routers.picpeak-backend.entrypoints=websecure" - "traefik.http.routers.picpeak-backend.tls=true" - "traefik.http.routers.picpeak-backend.tls.certresolver=letsencrypt" - "traefik.http.services.picpeak-backend.loadbalancer.server.port=3000" # Strip /api prefix when forwarding to backend - "traefik.http.middlewares.picpeak-stripprefix.stripprefix.prefixes=/api" - "traefik.http.routers.picpeak-backend.middlewares=picpeak-stripprefix" healthcheck: test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3 start_period: 60s frontend: image: picpeak-frontend:latest build: context: ./frontend dockerfile: Dockerfile args: - VITE_API_URL=/api - VITE_UMAMI_URL=${VITE_UMAMI_URL} - VITE_UMAMI_WEBSITE_ID=${VITE_UMAMI_WEBSITE_ID} restart: unless-stopped depends_on: - backend networks: - picpeak - traefik labels: - "traefik.enable=true" - "traefik.docker.network=traefik" # Frontend routing (catch-all for non-API routes) - "traefik.http.routers.picpeak-frontend.rule=Host(`picpeak.nothaft.cloud`)" - "traefik.http.routers.picpeak-frontend.entrypoints=websecure" - "traefik.http.routers.picpeak-frontend.tls=true" - "traefik.http.routers.picpeak-frontend.tls.certresolver=letsencrypt" - "traefik.http.services.picpeak-frontend.loadbalancer.server.port=80" # Lower priority than backend to ensure /api routes go to backend - "traefik.http.routers.picpeak-frontend.priority=1" db: image: postgres:14-alpine restart: unless-stopped environment: - POSTGRES_USER=${DB_USER:-picpeak} - POSTGRES_PASSWORD=${DB_PASSWORD} - POSTGRES_DB=${DB_NAME:-picpeak} # Allow connections from any host with password authentication - POSTGRES_HOST_AUTH_METHOD=scram-sha-256 - POSTGRES_INITDB_ARGS=--auth-host=scram-sha-256 --auth-local=trust volumes: - postgres_data:/var/lib/postgresql/data # Mount init script to create umami database - ./docker/postgres-init:/docker-entrypoint-initdb.d networks: - picpeak # Allow connections without SSL requirement from Docker network command: postgres -c ssl=off healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-picpeak}"] interval: 10s timeout: 5s retries: 5 umami: image: ghcr.io/umami-software/umami:postgresql-latest restart: unless-stopped environment: DATABASE_URL: postgresql://${DB_USER:-picpeak}:${DB_PASSWORD}@db:5432/umami DATABASE_TYPE: postgresql HASH_SALT: ${UMAMI_HASH_SALT} depends_on: db: condition: service_healthy networks: - picpeak - traefik labels: - "traefik.enable=true" - "traefik.docker.network=traefik" # Umami analytics routing - "traefik.http.routers.picpeak-umami.rule=Host(`analytics.picpeak.nothaft.cloud`)" - "traefik.http.routers.picpeak-umami.entrypoints=websecure" - "traefik.http.routers.picpeak-umami.tls=true" - "traefik.http.routers.picpeak-umami.tls.certresolver=letsencrypt" - "traefik.http.services.picpeak-umami.loadbalancer.server.port=3000" networks: picpeak: driver: bridge traefik: external: true volumes: postgres_data: