version: '3.8' services: tankstopp: restart: always deploy: resources: limits: cpus: '1.0' memory: 512M reservations: cpus: '0.5' memory: 256M environment: # Production Environment - TANKSTOPP_APP_ENVIRONMENT=production - TANKSTOPP_APP_DEBUG=false # Security Configuration - TANKSTOPP_SECURITY_SESSION_SECURE_COOKIES=true - TANKSTOPP_SECURITY_SESSION_HTTP_ONLY=true - TANKSTOPP_SECURITY_PASSWORD_MIN_LENGTH=12 - TANKSTOPP_SECURITY_PASSWORD_REQUIRE_SPECIAL_CHARS=true # Database Optimization - TANKSTOPP_DATABASE_CONNECTION_POOL_MAX_IDLE_CONNECTIONS=25 - TANKSTOPP_DATABASE_CONNECTION_POOL_MAX_OPEN_CONNECTIONS=200 - TANKSTOPP_DATABASE_CONNECTION_POOL_CONNECTION_MAX_LIFETIME=2h - TANKSTOPP_DATABASE_LOGGING_LEVEL=error - TANKSTOPP_DATABASE_MIGRATION_AUTO_MIGRATE=false - TANKSTOPP_DATABASE_PERFORMANCE_PREPARE_STATEMENTS=true # Logging Configuration - TANKSTOPP_LOGGING_LEVEL=info - TANKSTOPP_LOGGING_FORMAT=json - TANKSTOPP_LOGGING_OUTPUT=stdout # Performance Settings - TANKSTOPP_SERVER_READ_TIMEOUT=10s - TANKSTOPP_SERVER_WRITE_TIMEOUT=10s - TANKSTOPP_SERVER_IDLE_TIMEOUT=60s volumes: # Production data persistence - /var/lib/tankstopp/data:/app/data - /var/log/tankstopp:/app/logs # Production configuration - ./config.production.yaml:/app/config.yaml:ro healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/"] interval: 30s timeout: 5s retries: 3 start_period: 60s logging: driver: "json-file" options: max-size: "50m" max-file: "3" labels: - "traefik.enable=true" - "traefik.http.routers.tankstopp.rule=Host(`tankstopp.yourdomain.com`)" - "traefik.http.routers.tankstopp.tls=true" - "traefik.http.routers.tankstopp.tls.certresolver=letsencrypt" - "traefik.http.services.tankstopp.loadbalancer.server.port=8080" # Reverse Proxy (optional) traefik: image: traefik:v3.4 container_name: traefik restart: unless-stopped command: - "--api.dashboard=false" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" - "--certificatesresolvers.letsencrypt.acme.email=your-email@domain.com" - "--certificatesresolvers.letsencrypt.acme.storage=/acme.json" - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web" - "--global.sendAnonymousUsage=false" ports: - "80:80" - "443:443" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./acme.json:/acme.json networks: - tankstopp-network profiles: - proxy # Database backup service backup: image: alpine:3.22 container_name: tankstopp-backup restart: "no" environment: - BACKUP_RETENTION_DAYS=30 volumes: - /var/lib/tankstopp/data:/data:ro - /var/lib/tankstopp/backups:/backups command: | sh -c ' apk add --no-cache sqlite DATE=$$(date +%Y%m%d_%H%M%S) sqlite3 /data/fuel_stops.db ".backup /backups/fuel_stops_$$DATE.db" find /backups -name "fuel_stops_*.db" -mtime +$$BACKUP_RETENTION_DAYS -delete echo "Backup completed: fuel_stops_$$DATE.db" ' profiles: - backup networks: tankstopp-network: external: true volumes: tankstopp_data: {} tankstopp_logs: {}