# AOS — Agency Operating System # Docker Compose for production (PRD §5.7: Containers: app, postgres, caddy, backup) # Usage: docker compose up -d services: app: build: . container_name: aos-app restart: unless-stopped ports: - "3000:3000" environment: - NODE_ENV=production - DATABASE_URL=file:/app/db/custom.db - PORT=3000 - HOSTNAME=0.0.0.0 # Set these in .env or docker-compose.override.yml - ENCRYPTION_KEY=${ENCRYPTION_KEY:-change-me-32-bytes} - AUTH_SECRET=${AUTH_SECRET:-change-me-auth-secret} volumes: - aos-db:/app/db - aos-data:/app/data healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"] interval: 30s timeout: 5s retries: 3 start_period: 10s # Backup container (PRD §5.7: backup container) # Runs daily at 03:00, backs up SQLite + uploads volume backup: image: alpine:latest container_name: aos-backup restart: unless-stopped depends_on: app: condition: service_healthy environment: - BACKUP_SCHEDULE=0 3 * * * - BACKUP_RETENTION_DAYS=30 volumes: - aos-db:/data/db:ro - aos-backups:/backups entrypoint: - sh - -c - | apk add --no-cache sqlite curl echo "AOS Backup service started. Schedule: $$BACKUP_SCHEDULE" while true; do sleep 86400 TIMESTAMP=$$(date +%Y%m%d_%H%M%S) echo "[$$TIMESTAMP] Starting backup..." # Backup SQLite sqlite3 /data/db/custom.db ".backup /backups/aos_$$TIMESTAMP.db" # Checksum sha256sum /backups/aos_$$TIMESTAMP.db > /backups/aos_$$TIMESTAMP.db.sha256 # Cleanup old backups find /backups -name "aos_*.db" -mtime +$$BACKUP_RETENTION_DAYS -delete find /backups -name "aos_*.db.sha256" -mtime +$$BACKUP_RETENTION_DAYS -delete echo "[$$TIMESTAMP] Backup complete: aos_$$TIMESTAMP.db" done # Caddy reverse proxy (HTTPS) caddy: image: caddy:2-alpine container_name: aos-caddy restart: unless-stopped depends_on: app: condition: service_healthy ports: - "80:80" - "443:443" volumes: - caddy-data:/data - caddy-config:/config command: | caddy reverse-proxy --from :443 --to app:3000 volumes: aos-db: driver: local aos-data: driver: local aos-backups: driver: local caddy-data: caddy-config: