Инициализировать репозиторий «Дейл»
Первый коммит: модульный монолит ядра (.NET 10) и gRPC-сервисы ai/ml/telegram, фронтенд Vue 3/Vite/Tailwind, документация (ТЗ, инструкция пользователя, техдокументация, код-стайл), бэклог, скрипты развёртывания и архив прототипа LeadRadar.
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
# compose.dev.yml — dev-стек Дейла (этап 6, Task 20; Ruling 12).
|
||||
#
|
||||
# Полный стек: postgres + minio (хранилища), три автономных сервиса этапа 6
|
||||
# (telegram-service :5101, ai-service :5102, ml-service :5103) и core (deal-api:
|
||||
# HTTP :5080 + gRPC-ингресс :5082).
|
||||
#
|
||||
# Режимы интеграций core — флагами SERVICES__{ML,AI,TELEGRAM}__USELOCAL (Ruling 6):
|
||||
# * этот файл — сквозной gRPC-режим ВСЕГО стека «по-настоящему»: UseLocal=false заданы env
|
||||
# core-сервиса ниже, интеграции ходят в ml/ai/telegram-сервисы этой же compose-сети
|
||||
# (MlOutboxFlushScheduler → TrainBatch, GrpcAiClassifier/GrpcAiTools, GrpcTelegramClient).
|
||||
# Подъём всего стека одной командой: docker compose -f deploy/compose.dev.yml up -d --build
|
||||
# (см. также scripts/dev-smoke.sh — сквозная проверка с авто-очисткой).
|
||||
# * Local-заглушки (дефолт КОДА — appsettings.json, UseLocal:true) сохраняются для запуска core
|
||||
# с хоста БЕЗ сервисов (обычная dev-разработка, curl-приёмки этапов 2–5): поднимаются только
|
||||
# postgres/minio, core — dotnet run из src/core/Deal.Api. Код-дефолт не меняется — режим
|
||||
# переключает этот compose-файл (env ниже).
|
||||
#
|
||||
# Секреты dev (переопределяются .env/экспортом, шаблон ${VAR:-default}):
|
||||
# DEAL_SERVICE_TOKEN — единый service-token всех процессов (metadata gRPC, Ruling 1/2/13)
|
||||
# DEAL_ENCRYPTION_KEY — ключ AES-256-GCM шифрования секретов настроек core (32 байта base64)
|
||||
# DEAL_TELEGRAM_SESSION_KEY — ключ AES-256-GCM файлов сессий telegram-service (32 байта base64)
|
||||
# минио/БД creds — dev-значения ниже (в проде — этап 7, compose-prod + mTLS).
|
||||
#
|
||||
# Core в этом файле — «весь стек в docker» (эндпоинты — имена compose-сети). Альтернатива — core
|
||||
# с хоста (Ruling 12): поднимаются только postgres/minio и (по желанию) сервисы, core запускается
|
||||
# dotnet run, и сервисы ходят в ингресс хоста через DEAL_CORE_INGRESS=http://host.docker.internal:5082
|
||||
# (см. env telegram-service ниже).
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
container_name: deal-postgres
|
||||
environment:
|
||||
POSTGRES_DB: deal
|
||||
POSTGRES_USER: deal
|
||||
POSTGRES_PASSWORD: deal_dev_password
|
||||
ports:
|
||||
- "5433:5432" # 5432 может быть занят LeadRadar-стеком
|
||||
volumes:
|
||||
- deal_pgdata:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U deal -d deal"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 10
|
||||
|
||||
# MinIO для файлов проектных карточек (Ruling 4, план Task 6; образца-прототипа object_store.py).
|
||||
# Опционально: API работает и без него — LocalFileStorage (data/attachments) выбирается, пока MinIO не
|
||||
# сконфигурирован (Storage__Minio__* / DEAL_MINIO_*). Бакет deal-files создаётся приложением лениво при
|
||||
# первом upload (Ruling 4: EnsureBucket на первом put), отдельный init-контейнер не нужен.
|
||||
# Консоль: http://localhost:9001 (root deal_minio / deal_minio_secret).
|
||||
# Если 9000/9001 заняты LeadRadar-minio — поменяйте на 9100/9101 (и endpoint в конфигурации API).
|
||||
minio:
|
||||
image: minio/minio
|
||||
container_name: deal-minio
|
||||
environment:
|
||||
MINIO_ROOT_USER: deal_minio
|
||||
MINIO_ROOT_PASSWORD: deal_minio_secret
|
||||
ports:
|
||||
- "9000:9000" # S3 API
|
||||
- "9001:9001" # Web-консоль
|
||||
volumes:
|
||||
- deal_minio_data:/data
|
||||
command: server /data --console-address ":9001"
|
||||
|
||||
# core (deal-api) — HTTP :5080 + gRPC-ингресс telegram-service :5082 (план Task 12/20, Ruling 7/12).
|
||||
# Здесь core поднимается в сквозном gRPC-режиме (UseLocal=false ниже): сервисы этой же сети
|
||||
# вызываются по-настоящему; MlOutbox копится в БД и выгружается MlOutboxFlushScheduler (10 с).
|
||||
# Local-режим (дефолт appsettings.json) остаётся для запуска core с хоста без сервисов.
|
||||
core:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: src/core/Deal.Api/Dockerfile
|
||||
container_name: deal-core
|
||||
environment:
|
||||
ASPNETCORE_ENVIRONMENT: Development
|
||||
ASPNETCORE_URLS: http://0.0.0.0:5080
|
||||
GRPC_INGRESS_PORT: "5082"
|
||||
ConnectionStrings__DealPostgres: Host=postgres;Port=5432;Database=deal;Username=deal;Password=deal_dev_password
|
||||
DEAL_SERVICE_TOKEN: ${DEAL_SERVICE_TOKEN:-deal_dev_service_token}
|
||||
DEAL_ENCRYPTION_KEY: ${DEAL_ENCRYPTION_KEY:-MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY=}
|
||||
# gRPC-режим всего стека (Ruling 6): Local-заглушки кода (appsettings default true)
|
||||
# переключаются на gRPC-клиентов сервисов compose-сети. Хост-запуск core без compose
|
||||
# остаётся на Local (код-дефолт не менялся).
|
||||
Services__Ml__UseLocal: "false"
|
||||
Services__Ai__UseLocal: "false"
|
||||
Services__Telegram__UseLocal: "false"
|
||||
Services__Ml__Endpoint: http://ml-service:5103
|
||||
Services__Ai__Endpoint: http://ai-service:5102
|
||||
Services__Telegram__Endpoint: http://telegram-service:5101
|
||||
Storage__Minio__Endpoint: minio:9000
|
||||
Storage__Minio__AccessKey: deal_minio
|
||||
Storage__Minio__SecretKey: deal_minio_secret
|
||||
Storage__Minio__Bucket: deal-files
|
||||
Storage__Minio__Secure: "false"
|
||||
ports:
|
||||
- "5080:5080"
|
||||
- "5082:5082" # gRPC-ингресс telegram-service (сервисы ходят на http://core:5082 внутри сети)
|
||||
volumes:
|
||||
- deal_api_data:/app/data # data/encryption.key + data/attachments (Local-фолбэк файлов)
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "/bin/grpc_health_probe", "-addr=localhost:5082"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 10
|
||||
start_period: 15s
|
||||
|
||||
# telegram-service — gRPC-сервер Telegram (этап 6, Ruling 12; план Task 2). Отдельный процесс,
|
||||
# отдельное sln (src/telegram-service/Deal.Telegram.sln). Команды ядра приходят на localhost:5101
|
||||
# (SERVICES__Telegram__Endpoint — задачи 9–12), исходящий поток — в core-ингресс :5082
|
||||
# (SERVICES__CORE__INGRESS, Ruling 7; внутри compose — http://core:5082; при core на хосте задайте
|
||||
# DEAL_CORE_INGRESS=http://host.docker.internal:5082). Plaintext gRPC без mTLS (Ruling 2 — dev):
|
||||
# защита — общий service-token (DEAL_SERVICE_TOKEN, env хоста и контейнеров). Сессии тенантов —
|
||||
# файлы /data/sessions (Ruling 3), шифруются AES-256-GCM ключом DEAL_TELEGRAM_SESSION_KEY
|
||||
# (fail-closed: без ключа сервис не стартует). Контекст сборки — корень репозитория: csproj
|
||||
# ссылается на src/contracts/Deal.Proto.csproj (общий проект кодогенерации, Task 1).
|
||||
telegram-service:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: src/telegram-service/Deal.Telegram/Dockerfile
|
||||
container_name: deal-telegram-service
|
||||
environment:
|
||||
GRPC_PORT: "5101"
|
||||
DEAL_SERVICE_TOKEN: ${DEAL_SERVICE_TOKEN:-deal_dev_service_token}
|
||||
DEAL_TELEGRAM_SESSION_KEY: ${DEAL_TELEGRAM_SESSION_KEY:-ZmVkY2JhOTg3NjU0MzIxMGZlZGNiYTk4NzY1NDMyMTA=}
|
||||
DEAL_TELEGRAM_SESSION_DIR: /data/sessions
|
||||
SERVICES__CORE__INGRESS: ${DEAL_CORE_INGRESS:-http://core:5082}
|
||||
ports:
|
||||
- "5101:5101"
|
||||
volumes:
|
||||
- deal_tg_sessions:/data/sessions
|
||||
healthcheck:
|
||||
test: ["CMD", "/bin/grpc_health_probe", "-addr=localhost:5101"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 10
|
||||
|
||||
# ai-service — gRPC-сервер ИИ-фасада (этап 6, Ruling 12; план Task 4). Отдельный процесс,
|
||||
# отдельное sln (src/ai-service/Deal.Ai.sln). Промпты/классификацию/фильтр/ключи ядро шлёт на
|
||||
# localhost:5102 (SERVICES__Ai__Endpoint — задачи 7/8/15). Plaintext gRPC без mTLS (Ruling 2 —
|
||||
# dev): защита — общий service-token (DEAL_SERVICE_TOKEN, env хоста и контейнеров). Сервис без БД
|
||||
# (Ruling 5): конфиг провайдера (id/base/model/apiKey/api_style) приходит в теле каждого запроса
|
||||
# от ядра, персистентных файлов нет — volume не нужен. Контекст сборки — корень репозитория:
|
||||
# csproj ссылается на src/contracts/Deal.Proto.csproj (общий проект кодогенерации, Task 1).
|
||||
ai-service:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: src/ai-service/Deal.Ai/Dockerfile
|
||||
container_name: deal-ai-service
|
||||
environment:
|
||||
GRPC_PORT: "5102"
|
||||
DEAL_SERVICE_TOKEN: ${DEAL_SERVICE_TOKEN:-deal_dev_service_token}
|
||||
ports:
|
||||
- "5102:5102"
|
||||
healthcheck:
|
||||
test: ["CMD", "/bin/grpc_health_probe", "-addr=localhost:5102"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 10
|
||||
|
||||
# ml-service — gRPC-сервер ML (этап 6, Ruling 12; план Task 3). Отдельный процесс, отдельное sln
|
||||
# (src/ml-service/Deal.Ml.sln). Обучение и предсказания ядро шлёт на localhost:5103
|
||||
# (SERVICES__Ml__Endpoint — задачи 5/6/16). Plaintext gRPC без mTLS (Ruling 2 — dev): защита —
|
||||
# общий service-token (DEAL_SERVICE_TOKEN, env хоста и контейнеров). Модели тенантов — файлы
|
||||
# SQLite /data/ml/<tenantId>.sqlite (Ruling 4). Контекст сборки — корень репозитория: csproj
|
||||
# ссылается на src/contracts/Deal.Proto.csproj (общий проект кодогенерации, Task 1).
|
||||
ml-service:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: src/ml-service/Deal.Ml/Dockerfile
|
||||
container_name: deal-ml-service
|
||||
environment:
|
||||
GRPC_PORT: "5103"
|
||||
DEAL_SERVICE_TOKEN: ${DEAL_SERVICE_TOKEN:-deal_dev_service_token}
|
||||
DEAL_ML_DATA_DIR: /data/ml # файлы моделей data/ml/<tenantId>.sqlite на volume deal_ml_data (Ruling 4/12)
|
||||
ports:
|
||||
- "5103:5103"
|
||||
volumes:
|
||||
- deal_ml_data:/data/ml
|
||||
healthcheck:
|
||||
test: ["CMD", "/bin/grpc_health_probe", "-addr=localhost:5103"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 10
|
||||
|
||||
# Prometheus (профиль observability, этап 12/пакет A) — сбор /metrics всех 4 процессов (:9464)
|
||||
# внутри dev-сети. Подъём: docker compose -f deploy/compose.dev.yml --profile observability up -d.
|
||||
# Конфиг — общий deploy/observability/prometheus.yml (те же имена сервисов и таргеты). UI — 9090.
|
||||
prometheus:
|
||||
image: prom/prometheus:v3.5.0
|
||||
container_name: deal-prometheus
|
||||
profiles: ["observability"]
|
||||
command:
|
||||
- --config.file=/etc/prometheus/prometheus.yml
|
||||
- --storage.tsdb.path=/prometheus
|
||||
- --storage.tsdb.retention.time=15d
|
||||
ports:
|
||||
- "9090:9090"
|
||||
volumes:
|
||||
- ./observability/prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
||||
- ./observability/prometheus-rules.yml:/etc/prometheus/prometheus-rules.yml:ro
|
||||
- deal_prometheus_data:/prometheus
|
||||
|
||||
volumes:
|
||||
deal_pgdata:
|
||||
deal_minio_data:
|
||||
deal_tg_sessions:
|
||||
deal_ml_data:
|
||||
deal_api_data:
|
||||
deal_prometheus_data:
|
||||
Reference in New Issue
Block a user