services: db: image: postgres:17-alpine restart: unless-stopped environment: POSTGRES_DB: ${POSTGRES_DB:-mixmaker} POSTGRES_USER: ${POSTGRES_USER:-mixmaker} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U \"$${POSTGRES_USER}\" -d \"$${POSTGRES_DB}\""] interval: 10s timeout: 5s retries: 10 start_period: 10s migrations: build: context: ./backend restart: "no" command: ["migrate", "up"] environment: DATABASE_URL: ${DATABASE_URL:?DATABASE_URL is required} depends_on: db: condition: service_healthy api: build: context: ./backend restart: unless-stopped environment: APP_ENV: production HTTP_ADDR: :8080 PUBLIC_URL: ${PUBLIC_URL:?PUBLIC_URL is required} FRONTEND_URL: ${PUBLIC_URL:?PUBLIC_URL is required} DATABASE_URL: ${DATABASE_URL:?DATABASE_URL is required} SESSION_TTL: ${SESSION_TTL:-168h} DISCORD_CLIENT_ID: ${DISCORD_CLIENT_ID:?DISCORD_CLIENT_ID is required} DISCORD_CLIENT_SECRET: ${DISCORD_CLIENT_SECRET:?DISCORD_CLIENT_SECRET is required} DISCORD_REDIRECT_URL: ${DISCORD_REDIRECT_URL:?DISCORD_REDIRECT_URL is required} ADMIN_DISCORD_IDS: ${ADMIN_DISCORD_IDS:-} DISCORD_BOT_TOKEN: ${DISCORD_BOT_TOKEN:-} DISCORD_ANNOUNCEMENT_CHANNEL_ID: ${DISCORD_ANNOUNCEMENT_CHANNEL_ID:-} DISCORD_ANNOUNCEMENT_LOCALE: ${DISCORD_ANNOUNCEMENT_LOCALE:-ru} DISCORD_GUILD_ID: ${DISCORD_GUILD_ID:-} LOG_LEVEL: ${LOG_LEVEL:-info} depends_on: migrations: condition: service_completed_successfully expose: - "8080" healthcheck: test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:8080/healthz"] interval: 15s timeout: 5s retries: 5 start_period: 10s web: build: context: ./frontend args: VITE_API_BASE_URL: /api restart: unless-stopped depends_on: api: condition: service_healthy expose: - "80" healthcheck: test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://127.0.0.1/health"] interval: 15s timeout: 5s retries: 5 start_period: 10s volumes: postgres_data: