gendesign/tradein-mvp/docker-compose.prod.yml
lekss361 94cf199276
Some checks failed
Deploy Trade-In / changes (push) Successful in 5s
Deploy / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Successful in 26s
Deploy Trade-In / build-backend (push) Successful in 47s
Deploy / build-frontend (push) Successful in 29s
Deploy / build-backend (push) Successful in 1m24s
Deploy Trade-In / deploy (push) Successful in 40s
Deploy / build-worker (push) Successful in 2m57s
Deploy / deploy (push) Failing after 37s
feat(tradein): postgres_fdw live read of gendesign.cad_buildings (replaces snapshot) (#493)
Replaces tradein.cad_buildings snapshot with live postgres_fdw foreign table reading gendesign.v_tradein_cad_buildings. Fixes /trade-in/api/v1/geocode/reverse 500 (Nominatim ban) and address_not_geocoded for cadastre addresses (e.g. Хохрякова 81).

Security (deep-review fixes):
- 100_tradein_fdw_role.sql: passwordless CREATE ROLE; password set by deploy.yml ALTER ROLE bootstrap reading GENDESIGN_FDW_PASSWORD from backend/.env.runtime (via psql :'pw' var → format %L — injection-safe).
- core/fdw.py: regex whitelist [A-Za-z0-9_-]{32,256} on password, ValueError without echoing value, try/rollback on commit.
- 060_postgres_fdw_extension.sql: connect_timeout='3' on FOREIGN SERVER + ALTER ADD/SET fallback.
- geocoder.py: _cadastral_forward_sync / _cadastral_reverse_sync wrapped in asyncio.to_thread.
- 100_*.sql: REVOKE ALL ON ALL TABLES/SEQUENCES/FUNCTIONS IN SCHEMA public; only GRANT SELECT on v_tradein_cad_buildings.
- pg_user_mappings query handles PUBLIC mapping (usename IS NULL).

Tests: 3 SQL-injection guards on ensure_fdw_user_mapping + rewritten cadastral suite.
2026-05-24 08:57:30 +00:00

84 lines
3.4 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Trade-In MVP — production overlay для деплоя ВНУТРИ gendesign-стека.
#
# Запускается из /opt/gendesign/tradein-mvp/ на bot-server:
# docker compose -p gendesign \
# -f docker-compose.yml -f docker-compose.prod.yml up -d
#
# Особенности vs локального docker-compose.yml:
# - НЕТ своего Caddy и postgres-данных в bind mount
# (postgres контейнер один на всю машину, но изолированная БД tradein_mvp)
# - Образы тянутся из GHCR (build делает GitHub Actions)
# - Backend/frontend подключены к network gendesign_shared чтобы основной
# Caddy мог проксировать /trade-in/* → tradein-frontend
# - Frontend строится с basePath=/trade-in (см. next.config.ts)
services:
postgres:
image: postgis/postgis:16-3.4
container_name: tradein-postgres
environment:
POSTGRES_DB: tradein
POSTGRES_USER: ${TRADEIN_POSTGRES_USER:-tradein}
POSTGRES_PASSWORD: ${TRADEIN_POSTGRES_PASSWORD:?required}
volumes:
- tradein-postgres-data:/var/lib/postgresql/data
- ./backend/data/sql:/docker-entrypoint-initdb.d:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${TRADEIN_POSTGRES_USER:-tradein}"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- tradein-net
- gendesign_shared
backend:
image: ghcr.io/lekss361/gendesign-tradein-backend:${IMAGE_TAG:-latest}
container_name: tradein-backend
environment:
DATABASE_URL: "postgresql+psycopg://${TRADEIN_POSTGRES_USER:-tradein}:${TRADEIN_POSTGRES_PASSWORD}@postgres:5432/tradein"
PUBLIC_URL: "https://gendsgn.ru/trade-in"
CORS_ORIGINS: '["https://gendsgn.ru"]'
ENVIRONMENT: "production"
CONTACT_EMAIL: "${TRADEIN_CONTACT_EMAIL:-tradein@gendsgn.ru}"
YANDEX_GEOCODER_KEY: "${YANDEX_GEOCODER_KEY:-}"
# Защита /api/v1/admin/* — задаётся в .env.runtime. Пусто = открыто (dev).
ADMIN_TOKEN: "${ADMIN_TOKEN:-}"
# GlitchTip DSN — мониторинг ошибок (#396). Пусто = выключено.
GLITCHTIP_DSN: "${GLITCHTIP_DSN:-}"
GENDESIGN_FDW_PASSWORD: "${GENDESIGN_FDW_PASSWORD:-}"
depends_on:
postgres:
condition: service_healthy
restart: unless-stopped
networks:
- tradein-net
- gendesign_shared # чтобы Caddy gendesign-стека достучался
frontend:
image: ghcr.io/lekss361/gendesign-tradein-frontend:${IMAGE_TAG:-latest}
container_name: tradein-frontend
environment:
NODE_ENV: production
# Next.js standalone server.js читает HOSTNAME для bind-адреса.
# Docker по умолчанию ставит HOSTNAME=<container-id> → сервер слушает
# только свой hostname-интерфейс и недоступен как tradein-frontend:3000.
# Принудительно 0.0.0.0 чтобы Caddy достучался.
HOSTNAME: "0.0.0.0"
BACKEND_URL: "http://backend:8000" # internal SSR
depends_on: [backend]
restart: unless-stopped
networks:
- tradein-net
- gendesign_shared
volumes:
tradein-postgres-data:
name: tradein-postgres-data
networks:
tradein-net:
name: tradein-net
gendesign_shared:
external: true