# ============================================================ # Office Translator - Local Docker Compose (Mac Testing) # ============================================================ # Usage: ./deploy.sh start (or: docker compose -f docker-compose.local.yml --env-file .env.docker up -d) # Access: http://localhost (Nginx) | http://localhost:8000 (Backend direct) | http://localhost:3000 (Frontend direct) # # Services: PostgreSQL 16, Redis 7, Backend (FastAPI), Frontend (Next.js), Nginx (HTTP reverse proxy) # ============================================================ services: # =========================================== # PostgreSQL Database # =========================================== postgres: image: postgres:16-alpine container_name: translate-postgres restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER:-translate} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-translate_local_2026} POSTGRES_DB: ${POSTGRES_DB:-translate_db} PGDATA: /var/lib/postgresql/data/pgdata volumes: - postgres_data:/var/lib/postgresql/data ports: - "5432:5432" networks: - translate-network healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-translate} -d ${POSTGRES_DB:-translate_db}"] interval: 5s timeout: 5s retries: 10 start_period: 10s # =========================================== # Redis (Caching, Sessions, Rate Limiting) # =========================================== redis: image: redis:7-alpine container_name: translate-redis restart: unless-stopped command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru --loglevel warning volumes: - redis_data:/data ports: - "6379:6379" networks: - translate-network healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 5s retries: 5 start_period: 5s # =========================================== # Backend API (FastAPI) - Production build # =========================================== backend: build: context: . dockerfile: docker/backend/Dockerfile target: production container_name: translate-backend restart: unless-stopped extra_hosts: - "host.docker.internal:host-gateway" env_file: - .env.docker environment: # Override DB URL to use Docker service name DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-translate}:${POSTGRES_PASSWORD:-translate_local_2026}@postgres:5432/${POSTGRES_DB:-translate_db} REDIS_URL: redis://redis:6379/0 ENV: production PORT: "8000" WORKERS: "2" volumes: - uploads_data:/app/uploads - outputs_data:/app/outputs - logs_data:/app/logs - ./data:/app/data ports: - "8000:8000" networks: - translate-network depends_on: postgres: condition: service_healthy redis: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 15s timeout: 10s retries: 5 start_period: 30s # =========================================== # Frontend (Next.js) - Production build # =========================================== frontend: build: context: . dockerfile: docker/frontend/Dockerfile target: production args: NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-} BACKEND_URL: http://backend:8000 container_name: translate-frontend restart: unless-stopped environment: NODE_ENV: production PORT: "3000" HOSTNAME: "0.0.0.0" # Server-side proxy: backend accessible via Docker network BACKEND_URL: http://backend:8000 ports: - "${FRONTEND_PORT:-3010}:3000" networks: - translate-network depends_on: backend: condition: service_healthy healthcheck: test: ["CMD-SHELL", "node -e \"fetch('http://localhost:3000/').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\""] interval: 15s timeout: 10s retries: 3 start_period: 15s # =========================================== # Nginx Reverse Proxy (HTTP only for local) # =========================================== nginx: image: nginx:alpine container_name: translate-nginx restart: unless-stopped ports: - "${HTTP_PORT:-80}:80" volumes: - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./docker/nginx/conf.d/local.conf:/etc/nginx/conf.d/default.conf:ro - nginx_cache:/var/cache/nginx networks: - translate-network depends_on: backend: condition: service_healthy frontend: condition: service_healthy healthcheck: test: ["CMD", "nginx", "-t"] interval: 30s timeout: 10s retries: 3 # =========================================== # Networks # =========================================== networks: translate-network: driver: bridge # =========================================== # Volumes # =========================================== volumes: postgres_data: driver: local redis_data: driver: local uploads_data: driver: local outputs_data: driver: local logs_data: driver: local nginx_cache: driver: local