name: speech2text-mbip services: # ============================================================ # Nginx — Web Server # ============================================================ nginx: image: nginx:1.25-alpine container_name: speech2text_nginx restart: unless-stopped ports: - "80:80" volumes: - ./:/var/www/html:ro - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro depends_on: - app networks: - speech2text_net # ============================================================ # App — Laravel PHP-FPM # ============================================================ app: build: context: . dockerfile: Dockerfile container_name: speech2text_app restart: unless-stopped environment: - APP_ENV=${APP_ENV:-production} volumes: - ./:/var/www/html - ./docker/php/php.ini:/usr/local/etc/php/conf.d/app.ini:ro depends_on: mysql: condition: service_healthy redis: condition: service_started networks: - speech2text_net # ============================================================ # MySQL 8 # ============================================================ mysql: image: mysql:8.0 container_name: speech2text_mysql restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: ${MYSQL_DATABASE:-speech2text} MYSQL_USER: ${MYSQL_USER:-speech2text} MYSQL_PASSWORD: ${MYSQL_PASSWORD} volumes: - mysql_data:/var/lib/mysql ports: - "127.0.0.1:3307:3306" # host:3307 → container:3306 (elak conflict jika ada projek lain) healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"] interval: 10s timeout: 5s retries: 5 networks: - speech2text_net # ============================================================ # Redis — Queue & Cache # ============================================================ redis: image: redis:7-alpine container_name: speech2text_redis restart: unless-stopped command: redis-server --save 60 1 --loglevel warning volumes: - redis_data:/data networks: - speech2text_net # ============================================================ # Queue Worker — Laravel # ============================================================ queue-worker: build: context: . dockerfile: Dockerfile container_name: speech2text_queue restart: unless-stopped command: php artisan queue:work redis --sleep=3 --tries=3 --max-time=3600 --memory=256 volumes: - ./:/var/www/html depends_on: mysql: condition: service_healthy redis: condition: service_started networks: - speech2text_net # ============================================================ # Scheduler — Laravel Cron # ============================================================ scheduler: build: context: . dockerfile: Dockerfile container_name: speech2text_scheduler restart: unless-stopped command: php artisan schedule:work volumes: - ./:/var/www/html depends_on: mysql: condition: service_healthy redis: condition: service_started networks: - speech2text_net # ============================================================ # Transcription Worker — Python FastAPI + faster-whisper # INTERNAL ONLY — tidak boleh diakses dari luar Docker network # ============================================================ transcription-worker: build: context: ./docker/transcription-worker dockerfile: Dockerfile container_name: speech2text_transcription restart: unless-stopped environment: WHISPER_MODEL: ${WHISPER_MODEL:-small} WHISPER_LANGUAGE: ${WHISPER_LANGUAGE:-ms} WHISPER_DEVICE: ${WHISPER_DEVICE:-cpu} WHISPER_COMPUTE_TYPE: ${WHISPER_COMPUTE_TYPE:-int8} volumes: - whisper_models:/root/.cache/huggingface # cache model agar tidak download ulang # Port TIDAK di-expose ke host — internal sahaja networks: - speech2text_net # ============================================================ # Ollama — Optional Local LLM (disabled by default) # Uncomment jika OLLAMA_ENABLED=true # ============================================================ # ollama: # image: ollama/ollama # container_name: speech2text_ollama # restart: unless-stopped # volumes: # - ollama_data:/root/.ollama # networks: # - speech2text_net networks: speech2text_net: driver: bridge volumes: mysql_data: name: speech2text_mysql_data # nama eksplisit — susah ter-delete secara tidak sengaja labels: com.speech2text.description: "MySQL production data — JANGAN PADAM" redis_data: name: speech2text_redis_data whisper_models: name: speech2text_whisper_models # ollama_data: