Нормализовать переводы строк в LF

Решение по TD-STYLE-ANALYZERS: LF — инструменты проекта (Python/Node) пишут LF,
CRLF-.sh не работают на Linux CI (sh scripts/ci.sh), большинство файлов уже были
LF. Добавлен .gitattributes (* text=auto eol=lf, бинарные исключения),
.editorconfig переведён на lf, 1029 файлов конвертированы, git add --renormalize.
Из индекса убраны закравшиеся archive/**/__pycache__/*.pyc.
This commit is contained in:
Rustam Khalimov
2026-09-11 19:01:42 +03:00
parent 39c9bdc1b7
commit 713d554dc2
751 changed files with 94507 additions and 94486 deletions
+270 -270
View File
@@ -1,270 +1,270 @@
# 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:
# 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: