Сервисы и порты¶
Все сервисы deploy/local/compose.yml: профиль, образ или контекст сборки,
внутренний и публикуемый порт, зависимости, volumes, healthcheck, лимит
памяти и маршрут во внешнем контуре (Caddy). Статья для инженера, который
разворачивает стек, открывает порты на хосте или ищет, какой контейнер
отвечает на путь /….
Общая схема¶
flowchart LR
B[Браузер / харнесс / агент] ==>|80 / 443| CADDY[caddy<br/>edge]
CADDY ==>|/iam/*| IAM[iam-service:8010]
CADDY ==>|/api/v1/*, /health/*, /docs| CP[control-plane-api:8000]
CADDY ==>|/auth/*| KC[keycloak:8080]
CADDY ==>|/harness/*| HL[harness-launcher:8080]
CADDY ==>|/console/*| CON[console:8090]
CADDY ==>|/fleet/*| FC[fleet-controller:8040]
CADDY ==>|/memory/* только локально| MEM[memory-service:8077]
CADDY ==>|/ остальное| R[302 → /console/]
CP ==> MEM
CP ==> MINIO[(minio:9000)]
CP ==> IAM
CA[context-adapter] ==> MEM
CON ==> CP
CON ==> IAM
- Все контейнеры в одной сети
taimen(имя —${TAIMEN_NETWORK:-taimen_default}) и обращаются друг к другу по DNS-именам сервисов. -
Наружу смотрит только
caddy. Остальные сервисы публикуют порт исключительно на127.0.0.1— дляmake smoke,make bootstrapи отладки с хоста. -
У контейнера
caddyесть сетевой alias${TAIMEN_PUBLIC_HOST}: сервисы обращаются к Keycloak и IAM по публичному имени, чтобы issuer в токене совпадал с тем, что видит браузер.
Профили¶
По умолчанию make up поднимает core edge. Остальные профили включаются
явно: make up PROFILES="core notify edge" или
tools/compose --profile core --profile edge up -d.
| Профиль | Статус | Сервисы |
|---|---|---|
core |
ядро | iam-db, iam-service, control-plane-db, control-plane-api, control-plane-worker, context-adapter, memory-db, memory-service, minio, minio-bootstrap |
edge |
ядро | caddy, guide |
Зависимости между профилями
depends_on работает только внутри активных профилей. Launcher рабочих
мест ходит в Keycloak и IAM, а контейнеры людей — в control-plane-api,
поэтому поднимайте профили вместе (PROFILES="core idp harness edge").
Сводная таблица портов¶
| Сервис | Внутренний порт | Публикуется на хосте | Переменная порта | Путь в Caddy |
|---|---|---|---|---|
caddy |
80, 443 | 0.0.0.0:80, 0.0.0.0:443 |
EDGE_HTTP_PORT, EDGE_HTTPS_PORT |
— |
control-plane-api |
8000 | 127.0.0.1:18000 |
CP_HOST_PORT |
/api/v1/*, /health/*, /docs, /docs/*, /redoc, /redoc/*, /openapi.json |
memory-service |
8077 | 127.0.0.1:18001 |
MEMORY_HOST_PORT |
/memory/* (только в локальном Caddyfile) |
iam-service |
8010 | 127.0.0.1:18010 |
IAM_HOST_PORT |
/iam/* (префикс срезается) |
keycloak |
8080 (9000 — management, health) | 127.0.0.1:18081 |
KEYCLOAK_HOST_PORT |
/auth/* (без среза, Keycloak живёт под /auth) |
fleet-controller |
8040 | нет | — | /fleet/* (префикс срезается) |
harness-launcher |
8080 | нет | — | /harness/* (без среза, префикс снимает сам launcher) |
console |
8090 | нет | — | /console/* (без среза, сервер консоли живёт под /console; /console → 301) |
guide |
8080 | нет | — | /guide/* (префикс срезается) |
/ — всё, что не совпало выше |
— | — | — | редирект 302 на /console/ |
minio |
9000 | нет | — | нет |
базы *-db |
5432 | нет | — | нет |
control-plane-worker, context-adapter |
— | нет | — | нет |
Порядок маршрутов Caddy
Caddy выбирает первый совпавший handle. Специфичные префиксы (/iam/*,
/auth/*, /harness/* …) и матчер Control Plane @cp_api стоят раньше
общего handle, который редиректит всё остальное на /console/. Добавляя свой
маршрут, ставьте его перед общим handle.
Ядро (core)¶
iam-db¶
| Параметр | Значение |
|---|---|
| Образ | postgres:16-alpine |
| БД / роль | iam / iam, пароль ${IAM_POSTGRES_PASSWORD} |
| Volume | iam_db → /var/lib/postgresql/data |
| Healthcheck | pg_isready -U iam -d iam |
| Лимит памяти | ${PG_MEM_LIMIT:-256m} |
iam-service¶
| Параметр | Значение |
|---|---|
| Образ / сборка | ${IMAGE_PREFIX}/iam-service:${IMAGE_TAG}, контекст ${IAM_BUILD_CONTEXT:-./services/iam-service} |
| Команда | alembic upgrade head && uvicorn iam_service.app:app --host 0.0.0.0 --port 8010 |
| Порт | 8010 → 127.0.0.1:${IAM_HOST_PORT:-18010} |
| Зависит от | iam-db (healthy) |
| Секреты | iam_signing_key → /run/secrets/iam_signing_key (файл ${IAM_SIGNING_KEY_FILE}) |
| Healthcheck | GET http://127.0.0.1:8010/healthz |
| Лимит памяти | ${IAM_MEM_LIMIT:-256m} |
| Пользователь | uid 10001 |
control-plane-db¶
| Параметр | Значение |
|---|---|
| Образ | postgres:16-alpine |
| БД / роль | control_plane / control_plane |
| Volume | control_plane_db |
| Healthcheck | pg_isready -U control_plane -d control_plane |
| Лимит памяти | ${PG_MEM_LIMIT:-256m} |
control-plane-api¶
| Параметр | Значение |
|---|---|
| Образ / сборка | ${IMAGE_PREFIX}/control-plane:${IMAGE_TAG}, контекст ${CP_BUILD_CONTEXT:-.} (корень суперпроекта), Dockerfile services/control-plane/Dockerfile |
| Команда | alembic upgrade head && uvicorn control_plane.main:app --host 0.0.0.0 --port 8000 |
| Порт | 8000 → 127.0.0.1:${CP_HOST_PORT:-18000} |
| Зависит от | control-plane-db, memory-service, iam-service (все healthy) |
| env_file | ./secrets/control-plane-iam.env (необязательный) |
| Healthcheck | GET http://127.0.0.1:8000/health/ready |
| Лимит памяти | ${CP_MEM_LIMIT:-512m} |
| Пользователь | uid 10001 |
control-plane-worker¶
| Параметр | Значение |
|---|---|
| Образ | тот же, что у control-plane-api (не собирается отдельно) |
| Команда | python -m control_plane.worker |
| Порт | нет |
| Зависит от | control-plane-db (healthy), control-plane-api (healthy) |
| env_file | ./secrets/control-plane-iam.env |
| Healthcheck | нет |
| Лимит памяти | ${CP_WORKER_MEM_LIMIT:-256m} |
context-adapter¶
| Параметр | Значение |
|---|---|
| Образ | тот же, что у control-plane-api |
| Команда | python -m control_plane.worker.context_adapter |
| Порт | нет |
| Зависит от | control-plane-db, control-plane-api, memory-service (все healthy) |
| env_file | ./secrets/control-plane-iam.env |
| Healthcheck | нет |
| Лимит памяти | ${CP_WORKER_MEM_LIMIT:-256m} |
Один образ на три процесса
control-plane-api, control-plane-worker и context-adapter работают
на одном образе. Образ собирается только сервисом control-plane-api;
после сборки пересоздайте все три контейнера, иначе worker и адаптер
останутся на прежнем коде.
memory-db¶
| Параметр | Значение |
|---|---|
| Образ / сборка | ${IMAGE_PREFIX}/memory-db:${IMAGE_TAG}, контекст ${MEMORY_BUILD_CONTEXT:-./services/memory-service}/infra/memory-db (PostgreSQL 16 + pgvector + pg_trgm; образ основан на apache/age, расширение AGE сервис не использует) |
| БД / роль | company_brain / memory |
| Volume | memory_db |
| Healthcheck | pg_isready -U memory -d company_brain |
| Лимит памяти | ${MEMORY_DB_MEM_LIMIT:-512m} |
memory-service¶
| Параметр | Значение |
|---|---|
| Образ / сборка | ${IMAGE_PREFIX}/memory-service:${IMAGE_TAG}, контекст ${MEMORY_BUILD_CONTEXT:-.}, Dockerfile services/memory-service/Dockerfile |
| Порт | 8077 → 127.0.0.1:${MEMORY_HOST_PORT:-18001} |
| Зависит от | memory-db (healthy) |
| env_file | ./secrets/memory-service-iam.env (необязательный) |
| Healthcheck | GET http://127.0.0.1:8077/healthz |
| Лимит памяти | ${MEMORY_MEM_LIMIT:-512m} |
minio и minio-bootstrap¶
| Сервис | Образ | Порт | Зависит от | Volume | Healthcheck | Лимит |
|---|---|---|---|---|---|---|
minio |
cgr.dev/chainguard/minio@sha256:4692462f…, server /data |
9000, не публикуется | — | platform_minio |
mc ready local |
${MINIO_MEM_LIMIT:-256m} |
minio-bootstrap |
cgr.dev/chainguard/minio-client@sha256:19c80ef1… (-dev), одноразовый: бакет ${CP_S3_BUCKET}, политика cp-artifacts и пользователь ядра |
— | minio (healthy) |
— | — | — |
Хранит только содержимое артефактов ядра; см. Хранилище объектов.
console¶
| Параметр | Значение |
|---|---|
| Образ | ${IMAGE_PREFIX:-taimen}/console, сборка apps/console/Dockerfile (контекст — apps/console) |
| Пользователь | 10001:10001 |
| Порт | 8090, не публикуется; снаружи — /console/* через Caddy |
| Зависит от | iam-service, control-plane-api (healthy) |
| Секреты | runtime_console_oidc_secret, runtime_console_cookie_secret |
| Healthcheck | GET http://127.0.0.1:8090/console/healthz |
| Лимит памяти | 128m |
Сервер консоли и собранный интерфейс в одном образе; своей базы нет, сессии — в
зашифрованном файле на томе console_sessions. Профиль — core; в открытой поставке у
консоли свой профиль console, который поднимает и Keycloak (idp). Вход — OIDC IdP организации, в ядро и IAM — по внутренним именам от
имени вошедшего человека.
Так же консоль ходит во fleet и в launcher рабочих мест.
См. Консоль,
переменные RUNTIME_CONSOLE_* — в справочнике.
Периметр (edge)¶
caddy¶
| Параметр | Значение |
|---|---|
| Образ | caddy:2-alpine |
| Порты | ${EDGE_HTTP_PORT:-80}:80, ${EDGE_HTTPS_PORT:-443}:443 на всех интерфейсах |
| Volumes | ${CADDYFILE} → /etc/caddy/Caddyfile (read-only), caddy_data → /data (сертификаты ACME), caddy_config → /config |
| Сетевой alias | ${TAIMEN_PUBLIC_HOST:-taimen.localhost} |
| Healthcheck | нет |
Локальный deploy/caddy/Caddyfile.local обслуживает http://taimen.localhost
и http://localhost без ACME, пишет лог в stderr и сжимает ответы
(zstd, gzip). Промышленный Caddyfile задаётся переменной CADDYFILE и
повторяет ту же раскладку путей с TLS, но без маршрута /memory/*: память
наружу не публикуется. Подробнее — Периметр и TLS.
Правка Caddyfile на месте
Файл смонтирован bind-mount'ом и держит inode. Если заменить файл через
mv, caddy reload перечитает старую версию. Правьте файл на месте или
пересоздайте контейнер: tools/compose up -d --force-recreate caddy.
Вход людей (idp)¶
| Сервис | Образ / сборка | Порт | Зависит от | Volume / файлы | Healthcheck | Лимит |
|---|---|---|---|---|---|---|
keycloak-db |
postgres:16-alpine, БД и роль keycloak |
— | — | keycloak_db |
pg_isready -U keycloak -d keycloak (10 s × 10) |
${PG_MEM_LIMIT} |
realm-render |
busybox:1.36, одноразовый: подставляет TAIMEN_PUBLIC_URL в шаблон realm |
— | — | deploy/keycloak/platform-realm.json → /template, realm_import → /import |
— | — |
keycloak |
quay.io/keycloak/keycloak:26.5.2, start --import-realm |
8080 → 127.0.0.1:18081 |
keycloak-db (healthy), realm-render (завершён) |
realm_import (read-only) |
GET /auth/health/ready на порту 9000 (15 s × 20, start 40 s) |
${KEYCLOAK_MEM_LIMIT:-768m} |
Realm импортируется один раз
--import-realm импортирует realm только при первом старте с пустой
БД. Правки шаблона на существующий realm не попадают — меняйте живой
realm через Admin API или скрипты deploy/keycloak/. См.
Keycloak — внешний IdP.
Рабочие места (harness)¶
| Сервис | Образ / сборка | Порт | Зависит от | Volume / файлы | Healthcheck | Лимит |
|---|---|---|---|---|---|---|
harness-image |
контекст ./services/human-harness, Dockerfile; только сборка образа рабочего места (/bin/true) |
— | — | — | — | — |
harness-docker-proxy |
tecnativa/docker-socket-proxy:v0.4.1; разрешены только контейнеры и volume |
2375, не публикуется | — | /var/run/docker.sock (read-only) |
нет | 64m |
harness-launcher |
контекст ./services/human-harness, packages/launcher/Dockerfile |
8080, не публикуется | harness-docker-proxy (запущен), harness-image (завершён) |
harness_launcher; secrets/harness/people.json; секреты harness_cookie_secret, harness_iam_bootstrap_token |
GET /harness/_launcher/health (15 s × 5) |
128m |
Контейнеры людей launcher создаёт сам (вне deploy/local/compose.yml), см.
Рабочее место человека.
Сети профиля: harness-docker-proxy — только во внутренней сети harness-control
(вместе с launcher'ом); контейнеры людей — в сети harness-people, куда, кроме них,
подключены только harness-launcher, control-plane-api, notification-service и
caddy. Подробно — Изоляция рабочих мест.
Fleet (fleet)¶
Контроллер узлов и размещения декларативных агентов (TAI-ADR-0052). Узлы
(fleet-node) работают на машинах исполнителей вне этого compose и ходят к
контроллеру только исходящими запросами через Caddy /fleet/*.
| Сервис | Образ / сборка | Порт | Зависит от | Volume / env | Healthcheck | Лимит |
|---|---|---|---|---|---|---|
fleet-controller |
${IMAGE_PREFIX:-taimen}/fleet-controller:${IMAGE_TAG:-local}, контекст ${FLEET_BUILD_CONTEXT:-.}, Dockerfile services/fleet/Dockerfile; команда fleet-controller serve |
8040, не публикуется | control-plane-api, iam-service (healthy) |
fleet_data → /data; env_file ./secrets/fleet-iam.env |
GET /healthz на 127.0.0.1:8040 |
${FLEET_MEM_LIMIT:-128m} |
Без secrets/fleet-iam.env (bootstrap, шаг 5d) все маршруты, кроме
/healthz, отвечают 503 not_configured. Переменные — в
Переменных окружения, устройство — в
Узлах и fleet.
Healthcheck'и и smoke¶
У Python-сервисов ядра общий шаблон healthcheck: интервал 5 s, таймаут
5 s, 30 попыток; проверка — urllib.request.urlopen на 127.0.0.1
(не localhost: в slim-образах localhost может резолвиться в IPv6
::1, где сервер не слушает).
make smoke (tools/smoke.py) проверяет поднятые сервисы по портам на
127.0.0.1 и пропускает не запущенные:
| Сервис | Порт по умолчанию | Путь |
|---|---|---|
iam-service |
18010 | /healthz |
control-plane-api |
18000 | /health/ready |
memory-service |
18001 | /healthz |
keycloak |
18081 | /auth/realms/platform |
Ответ с кодом < 400 — OK, иначе ERR и ненулевой код выхода.
Volumes¶
| Volume | Сервис | Что хранит |
|---|---|---|
iam_db |
iam-db |
Tenants, principals, credentials IAM |
control_plane_db |
control-plane-db |
Work graph, журнал событий, bindings |
memory_db |
memory-db |
Граф знаний, чанки, наблюдения |
keycloak_db |
keycloak-db |
Realm, пользователи и пароли Keycloak |
platform_minio |
minio |
Содержимое артефактов ядра (имя тома историческое) |
harness_launcher |
harness-launcher |
Состояние launcher'а рабочих мест |
realm_import |
realm-render, keycloak |
Отрендеренный realm |
dex_config |
dex-render, dex |
Отрендеренный конфиг Dex (профиль idp-dex) |
fleet_data |
fleet-controller |
SQLite: узлы, размещения, личности агентов, шифротексты PAT |
caddy_data, caddy_config |
caddy |
Сертификаты и состояние Caddy |
Имена задаются переменными VOLUME_* (см.
Переменные окружения). make down volumes не удаляет.
Docker-секреты¶
| Секрет | Файл по умолчанию | Кому |
|---|---|---|
iam_signing_key |
./secrets/iam-signing.pem |
iam-service |
harness_cookie_secret |
./secrets/harness/cookie-secret |
harness-launcher |
harness_iam_bootstrap_token |
из переменной IAM_BOOTSTRAP_TOKEN |
harness-launcher |
runtime_console_oidc_secret |
./secrets/runtime-console-oidc-secret (RUNTIME_CONSOLE_OIDC_SECRET_FILE) |
console, dex-render |
runtime_console_cookie_secret |
./secrets/runtime-console-cookie-secret (RUNTIME_CONSOLE_COOKIE_SECRET_FILE) |
console |
Контейнеры читают секреты под непривилегированным uid (10001 у сервисов
ядра). На Linux выполните chown 10001 для файлов в secrets/, права
оставьте 600.