Локальний запуск
Як підняти Kumquat локально через make up-local — env-файли, профілі, override і Makefile.local.
Увесь стек піднімається одним docker compose з кореня репо, а щоденна команда
загорнута в make up-local. Джерело правди — docker-compose.yaml: сервіси, порти
й коментарі до кожного опціонального сервісу живуть там. Персональні налаштування —
у двох непідтрекованих файлах, docker-compose.override.yaml і Makefile.local
(обидва в .gitignore), приклади яких наведено нижче.
MongoDB завжди віддалена (MONGO__URI з backend/.env): застосунок слухає
зміни колекцій (change streams), а локальний standalone-контейнер їх не підтримує.
Швидкий старт
# 1. env-файли
cp backend/.env.dist backend/.env # Mongo, Clerk, ClickHouse, …
cp frontend/.env.dist frontend/.env.local # Clerk publishable key, NEXT_PUBLIC_API_URL
# 2. персональні файли — вміст нижче на цій сторінці
cp docker-compose.override.yaml.dist docker-compose.override.yaml
$EDITOR Makefile.local # приклад — у розділі «Makefile.local»
# 3. увесь стек з live-reload
make up-local
Відкрий http://localhost:3000.
| Сервіс | Адреса |
|---|---|
| frontend | http://localhost:3000 |
| api | http://localhost:8081 |
agent (профіль analyst-agent) |
http://localhost:8082 |
docs (профіль docs) |
http://localhost:4321 |
| redis | localhost:6379 |
clickhouse (профіль local-clickhouse) |
localhost:8123 (HTTP), localhost:9191 (native) |
Запуск через make up-local
make up-local — це docker compose ... up --build --watch --force-recreate з
потрібними профілями (за замовчуванням worker). Профілі міняються без правки
файлу:
make up-local # api + frontend + redis + worker
make up-local PROFILES="worker analyst-agent" # + агент-аналітик
make up-local PROFILES="worker docs" # + сайт документації
make down-local # зупинити (з тими ж PROFILES, див. нижче)
--watch синхронізує код у контейнери: api перезавантажується сам (--reload),
worker рестартує, frontend/src підхоплює Next.js dev-сервер, а зміна
pyproject.toml / uv.lock / package.json перезбирає образ.
- Watch бачить лише зміни, зроблені поки він працює.
up-localзавжди передає--build, тож код, змінений поки compose стояв, потрапить в образ при старті. --watchне поєднується з-d: команда має лишатися у foreground.--force-recreateперестворює контейнери, навіть якщо конфіг не змінився, — тому правка.envпідхоплюється простим перезапуском (env-файли читаються лише при створенні контейнера).
Профілі (--profile)
Сервіс із ключем profiles: не стартує при звичайному docker compose up — лише
коли один із його профілів активний. Сервіс без profiles: стартує завжди. Так один
docker-compose.yaml описує і мінімальний стек, і все опціональне, а що саме
піднімати, вирішує команда.
У Kumquat завжди стартують api, frontend, redis. Решта — за профілем:
| Профіль | Сервіс | Навіщо |
|---|---|---|
worker |
worker |
Celery (черги cpu,io,llm,graphs). Без нього фонові задачі — генерація, графи, експорт — стоять у черзі. |
analyst-agent |
agent |
Агент-аналітик, архітектура. |
local-clickhouse |
clickhouse |
Локальний ClickHouse замість port-forward із k8s. |
docs |
docs |
Цей сайт документації з hot-reload. |
cli, gdrive-sync, creative-metrics-cli |
однойменні | Одноразові CLI-контейнери для docker compose run. |
Як вмикати без Makefile:
# прапорець глобальний — стоїть ПЕРЕД підкомандою, може повторюватися
docker compose --profile worker --profile analyst-agent up --watch
# те саме через змінну оточення (через кому)
COMPOSE_PROFILES=worker,analyst-agent docker compose up --watch
# явно названий сервіс вмикає свій профіль сам — --profile не потрібен
docker compose run --build --rm cli show-settings
docker compose up docs --watch
Пастки:
downтеж дивиться на профілі.docker compose downбез--profileне зупинитьworkerчиagent— передавай ті самі профілі, що й вup(make down-local PROFILES="...").- Профіль не вмикає профільні залежності. Якщо сервіс без профілю має
depends_onна профільний, compose потягне той у коженup— і профіль втратить сенс. Тому в override не додаютьdepends_onна профільні сервіси. - Override не активує профіль. Секція
agent:вdocker-compose.override.yamlлише міняє його env; самagentстартує, тільки коли увімкненоanalyst-agent. - Перевірити, що реально підніметься:
docker compose --profile worker config --services.
docker-compose.override.yaml
Compose автоматично домерджує docker-compose.override.yaml поверх
docker-compose.yaml, якщо файл лежить поруч і -f не передано (з явними -f, як
у Makefile.local, треба перелічити обидва). environment з override має пріоритет
над env_file, тож backend/.env редагувати не доводиться — override лише
перенаправляє сервіси на інші хости.
Типовий файл веде api/worker/agent і CLI-контейнери на ClickHouse, прокинутий із k8s через port-forward на хост.
# Untracked. Start from docker-compose.override.yaml.dist.
#
# ClickHouse: port-forward from k8s, listening beyond loopback — docker bridge
# traffic arrives from 172.17.0.1, not 127.0.0.1:
# kubectl -n clickhouse port-forward svc/clickhouse --address 0.0.0.0 8123:8123
# With --profile local-clickhouse instead, drop the CLICKHOUSE__HOST /
# ANALYST_AGENT__CH__HOST lines.
services:
api:
environment:
- CLICKHOUSE__HOST=host.docker.internal
- LOG_LEVEL=INFO
extra_hosts:
- "host.docker.internal:host-gateway"
worker:
environment:
- CLICKHOUSE__HOST=host.docker.internal
extra_hosts:
- "host.docker.internal:host-gateway"
agent:
environment:
- ANALYST_AGENT__CH__HOST=host.docker.internal
extra_hosts:
- "host.docker.internal:host-gateway"
cli:
environment:
- CLICKHOUSE__HOST=host.docker.internal
extra_hosts:
- "host.docker.internal:host-gateway"
creative-metrics-cli:
environment:
- CLICKHOUSE__HOST=host.docker.internal
extra_hosts:
- "host.docker.internal:host-gateway"
host.docker.internal:host-gatewayпотрібен на Linux; Docker Desktop на macOS резолвить це ім’я й сам, але запис не заважає.- Без
--address 0.0.0.0port-forward слухає лише127.0.0.1, і з контейнера ClickHouse недоступний — помилка виглядає як таймаут, а не відмова в доступі.
Локальний ClickHouse
--profile local-clickhouse піднімає порожній однонодовий ClickHouse. db/init.sql
змонтовано як init-скрипт, але він розрахований на кластер ml (ON CLUSTER,
Replicated*MergeTree) і на одній ноді схему не створює — подробиці в коментарі до
сервісу clickhouse у docker-compose.yaml. Для більшості задач простіше
port-forward.
Makefile.local
Кореневий Makefile робить -include Makefile.local, тож персональні таргети
з’являються в make help поруч зі спільними й не потрапляють у git.
# Untracked; pulled in by `-include Makefile.local` in the root Makefile.
ENV_FILE := backend/.env
COMPOSE := docker compose --env-file $(ENV_FILE) -f docker-compose.yaml -f docker-compose.override.yaml
# Override per run: make up-local PROFILES="worker analyst-agent"
PROFILES ?= worker
PROFILE_FLAGS := $(foreach p,$(PROFILES),--profile $(p))
.PHONY: up-local
up-local: ## Start the stack with my profiles and live-reload
$(COMPOSE) $(PROFILE_FLAGS) up --build --watch --force-recreate
.PHONY: down-local
down-local: ## Stop the stack (same profiles, or profiled services keep running)
$(COMPOSE) $(PROFILE_FLAGS) down
- Рядки рецептів у Makefile мають починатися з табуляції, не пробілів, інакше
missing separator. --env-fileзадає файл для підстановки${VAR}у самому compose-файлі — це не те саме, щоenv_file:сервісу, який передає змінні в контейнер.- Імена таргетів не мають збігатися з таргетами кореневого
Makefile— make попередить про перевизначення, і спрацює останнє.