ci / build-test (push) Canceled after 0s
SaaS-мониторинг Telegram: ядро (модули Cards/Kanban/Pipeline/Tenants/Settings/ Discovery, Api, Infrastructure), сервисы telegram/ai/ml/storage, фронт Vue, контракты и grpc-hosting, деплой-конфиги (dev/prod/observability/CI-раннер), Gitea Actions CI, документация (ТЗ, техдок, api-map, код-стайл, планы, бэклог). Текущее состояние: все этапы роадмапа 0–12 закрыты, сборка 5 sln 0/0, тесты 1340/130/52/38/9 зелёные.
271 lines
14 KiB
YAML
271 lines
14 KiB
YAML
# compose.dev.yml — dev-стек Дейла (этап 6, Task 20; Ruling 12).
|
||
#
|
||
# Полный стек: postgres + minio (хранилища), три автономных сервиса этапа 6
|
||
# (telegram-service :5101, ai-service :5102, ml-service :5103, storage-service :5104) и 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 ниже).
|
||
|
||
# Общий hardening прикладных сервисов (BL-IMG-HARDEN): read-only root FS + tmpfs /tmp,
|
||
# запрет новых привилегий и сброс capabilities. Данные — только в именованных volume.
|
||
x-service-hardening: &service-hardening
|
||
read_only: true
|
||
tmpfs:
|
||
- /tmp
|
||
security_opt:
|
||
- no-new-privileges:true
|
||
cap_drop:
|
||
- ALL
|
||
|
||
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
|
||
<<: *service-hardening
|
||
mem_limit: 1g
|
||
cpus: 1.5
|
||
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
|
||
Services__Storage__Endpoint: http://storage-service:5104
|
||
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
|
||
<<: *service-hardening
|
||
mem_limit: 512m
|
||
cpus: 1.0
|
||
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
|
||
DEAL_LOGS_DIR: /tmp/logs
|
||
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
|
||
<<: *service-hardening
|
||
mem_limit: 512m
|
||
cpus: 1.0
|
||
environment:
|
||
GRPC_PORT: "5102"
|
||
DEAL_SERVICE_TOKEN: ${DEAL_SERVICE_TOKEN:-deal_dev_service_token}
|
||
DEAL_LOGS_DIR: /tmp/logs
|
||
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
|
||
<<: *service-hardening
|
||
mem_limit: 768m
|
||
cpus: 1.0
|
||
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)
|
||
DEAL_LOGS_DIR: /tmp/logs
|
||
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
|
||
|
||
# storage-service — общий gRPC-сервис данных (вложения источников). Отдельный процесс, отдельное sln
|
||
# (src/storage-service/Deal.Storage.sln). Загрузка/выгрузка/стат/удаление объектов; тип объекта
|
||
# определяет сервис. Бэкенд — MinIO. Защита — общий service-token (DEAL_SERVICE_TOKEN).
|
||
storage-service:
|
||
build:
|
||
context: ..
|
||
dockerfile: src/storage-service/Deal.Storage/Dockerfile
|
||
container_name: deal-storage-service
|
||
<<: *service-hardening
|
||
mem_limit: 512m
|
||
cpus: 1.0
|
||
environment:
|
||
GRPC_PORT: "5104"
|
||
DEAL_SERVICE_TOKEN: ${DEAL_SERVICE_TOKEN:-deal_dev_service_token}
|
||
DEAL_STORAGE_ENDPOINT: minio:9000
|
||
DEAL_STORAGE_ACCESS_KEY: deal_minio
|
||
DEAL_STORAGE_SECRET_KEY: deal_minio_secret
|
||
DEAL_STORAGE_BUCKET: deal-attachments
|
||
DEAL_STORAGE_SECURE: "false"
|
||
DEAL_LOGS_DIR: /tmp/logs
|
||
ports:
|
||
- "5104:5104"
|
||
depends_on:
|
||
- minio
|
||
healthcheck:
|
||
test: ["CMD", "/bin/grpc_health_probe", "-addr=localhost:5104"]
|
||
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:
|