Files
crank/docs/deployment.md
T
2026-03-25 22:22:22 +03:00

7.5 KiB

Deployment

1. Назначение документа

Этот документ фиксирует platform-agnostic модель деплоя проекта.

Он отвечает на вопросы:

  • какие deployment artifacts должны быть в репозитории;
  • как проект должен запускаться в production-like окружении;
  • как routing должен работать через reverse proxy;
  • что должен делать CD pipeline.

Документ не привязан к конкретному hypervisor, cloud provider, типу VM или домашней инфраструктуре.

2. Базовая модель деплоя

Для MVP принимается контейнерная модель:

  • admin-api, mcp-server и ui упаковываются в контейнеры;
  • PostgreSQL запускается как отдельный контейнер;
  • сервисы запускаются через docker-compose;
  • перед приложением находится reverse proxy;
  • CI проверяет качество, CD доставляет и перезапускает сервисы.

3. Что должно быть в репозитории

В проекте должны существовать:

  • Dockerfile для apps/admin-api;
  • Dockerfile для apps/mcp-server;
  • Dockerfile для apps/ui или отдельный production build flow для UI;
  • docker-compose.yml;
  • .env.example;
  • .github/workflows/ci.yml;
  • .github/workflows/deploy.yml;
  • примеры reverse proxy конфигураций.

Рекомендуемое стартовое распределение портов:

  • ui -> 3000
  • admin-api -> 3001
  • mcp-server -> 3002

4. Production-like runtime состав

Минимальный набор сервисов:

  • ui
  • admin-api
  • mcp-server
  • postgres

Persistent data:

  • volume для postgres;
  • volume или bind mount для artifact storage.

5. Рекомендуемая routing model

Под одним доменом:

  • / -> ui
  • /api/admin/ -> admin-api
  • /mcp/ -> mcp-server

Это позволяет:

  • централизовать TLS;
  • не плодить поддомены без необходимости;
  • держать demo URL простым;
  • использовать один reverse proxy для UI, API и MCP.

6. Требования к reverse proxy

Reverse proxy должен обеспечивать:

  • TLS termination;
  • редирект HTTP -> HTTPS;
  • X-Forwarded-* headers;
  • отключение buffering для MCP endpoint;
  • увеличенные таймауты для долгих runtime-запросов;
  • корректную маршрутизацию UI, admin API и MCP.

Особенно для mcp-server важно:

  • proxy_buffering off;
  • proxy_request_buffering off;
  • длинный proxy_read_timeout.

7. Пример nginx

server {
    listen 80;
    server_name example.com;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    client_max_body_size 25m;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_http_version 1.1;

    location / {
        proxy_pass http://ui:3000;
    }

    location /api/admin/ {
        proxy_pass http://admin-api:3001/;
    }

    location /mcp/ {
        proxy_pass http://mcp-server:3002/;
        proxy_buffering off;
        proxy_request_buffering off;
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
    }
}

8. Пример Traefik

services:
  ui:
    labels:
      - traefik.enable=true
      - traefik.http.routers.ui.rule=Host(`example.com`) && PathPrefix(`/`)
      - traefik.http.services.ui.loadbalancer.server.port=3000

  admin-api:
    labels:
      - traefik.enable=true
      - traefik.http.routers.admin.rule=Host(`example.com`) && PathPrefix(`/api/admin`)
      - traefik.http.services.admin.loadbalancer.server.port=3001

  mcp-server:
    labels:
      - traefik.enable=true
      - traefik.http.routers.mcp.rule=Host(`example.com`) && PathPrefix(`/mcp`)
      - traefik.http.services.mcp.loadbalancer.server.port=3002

Для production нужно отдельно проверить timeout behavior на MCP маршруте.

9. Требования к docker-compose

docker-compose.yml должен:

  • поднимать postgres, admin-api, mcp-server, ui;
  • использовать env vars вместо hardcoded config;
  • иметь persistent storage для БД и artifacts;
  • поддерживать настраиваемый bind host для published ports;
  • публиковать ui, admin-api и mcp-server на loopback, если reverse proxy живет на том же хосте;
  • публиковать ui, admin-api и mcp-server на LAN bind address или 0.0.0.0, если reverse proxy вынесен на отдельный хост;
  • не публиковать внутренние сервисы наружу без необходимости;
  • содержать healthchecks.

Практически это должно быть управляемо через env вроде MCPAAS_PUBLISH_HOST:

  • 127.0.0.1 для local reverse proxy на том же Linux host;
  • конкретный внутренний IP или 0.0.0.0 для отдельного центрального reverse proxy в LAN.

10. Healthchecks

Нужны как минимум:

  • GET /health для admin-api
  • GET /health для mcp-server

CD не должен считать deployment успешным, пока эти endpoints не начали возвращать 200 OK.

11. CI и CD

11.1. CI

CI должен выполнять:

  • cargo fmt --all --check
  • cargo check --workspace
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo test --workspace --all-targets

11.2. CD

CD для MVP должен:

  • запускаться только после успешного CI на main или вручную;
  • собирать production artifacts;
  • доставлять deployment files на целевой Linux host;
  • выполнять controlled restart;
  • проверять health endpoints после запуска.

Минимальный flow:

  1. push в main
  2. успешный CI
  3. build images или удаленная сборка на хосте
  4. upload env и deployment files
  5. docker compose config -q
  6. docker compose up -d
  7. healthcheck verification для ui, admin-api, mcp-server

Для MVP допустим deployment с удаленной сборкой на целевом Linux host через ssh + rsync + docker compose up -d --build, если не используется отдельный container registry.

12. Что нельзя забыть

  • TLS и renewal сертификатов;
  • backup для postgres и artifact storage;
  • секреты вне репозитория;
  • ограничение доступа к admin-api;
  • rollback на предыдущий image tag или предыдущую compose revision.