# Production Docker Compose Configuration # Usage: docker compose -f docker-compose.prod.yml up -d # # IMPORTANT: Database data is preserved in ./shared/db/data volume services: db: image: postgres:17-alpine container_name: aurora_db restart: unless-stopped environment: - POSTGRES_USER=${DB_USER} - POSTGRES_PASSWORD=${DB_PASSWORD} - POSTGRES_DB=${DB_NAME} volumes: # Database data - persisted across container rebuilds - ./shared/db/data:/var/lib/postgresql/data - ./shared/db/log:/var/log/postgresql networks: - internal healthcheck: test: [ "CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}" ] interval: 10s timeout: 5s retries: 5 # Security: limit resources deploy: resources: limits: memory: 512M socket-proxy: image: tecnativa/docker-socket-proxy container_name: socket_proxy restart: unless-stopped environment: - CONTAINERS=1 - POST=1 - BUILD=1 - NETWORKS=1 - IMAGES=1 # Needed for pulling/pruning volumes: - /var/run/docker.sock:/var/run/docker.sock:ro networks: - internal app: container_name: aurora_app restart: unless-stopped build: context: . dockerfile: Dockerfile.prod target: production image: aurora-app:latest ports: - "127.0.0.1:3000:3000" # Volumes for bot-triggered deployments volumes: # Project directory - allows git pull and rebuild - .:/app/deploy working_dir: /app environment: - NODE_ENV=production - HOST=0.0.0.0 - DB_USER=${DB_USER} - DB_PASSWORD=${DB_PASSWORD} - DB_NAME=${DB_NAME} - DB_PORT=5432 - DB_HOST=db - DISCORD_BOT_TOKEN=${DISCORD_BOT_TOKEN} - DISCORD_GUILD_ID=${DISCORD_GUILD_ID} - DISCORD_CLIENT_ID=${DISCORD_CLIENT_ID} - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME} # Deploy directory path for bot-triggered deployments - DEPLOY_DIR=/app/deploy - DOCKER_HOST=tcp://socket-proxy:2375 depends_on: db: condition: service_healthy socket-proxy: condition: service_started networks: - internal - web # Security: limit resources deploy: resources: limits: memory: 1G # Logging configuration logging: driver: "json-file" options: max-size: "10m" max-file: "3" networks: internal: driver: bridge internal: true # No external access - DB isolated web: driver: bridge # App accessible from host (via reverse proxy)