Установка

Запуск одной командой

Что поднимает docker compose up, на каких портах, где демо-аккаунт и где остаются данные.

На этой странице · 6

Стенд целиком — база, шлюз и кабинет — поднимается из репозитория одной командой. Ничего, кроме Docker, ставить не нужно: зависимости, генерация клиента Prisma и сборка кабинета происходят при сборке образа.

git clone https://github.com/darkClaw921/apistend.git
cd apistend
docker compose up

Что именно поднимается

СервисКонтейнерПорт снаружиЧто это
postgresapistend-postgres5433PostgreSQL 17 (alpine)
apiapistend-api8080мок-шлюз, каталог, ключи, журнал, вебхуки, туннель
webapistend-web3100лендинг и кабинет (Next.js)

Порт базы снаружи — 5433, а не 5432: иначе он конфликтует с PostgreSQL, установленным на машине обычным способом. Внутри сети compose база слушает 5432, и DATABASE_URL контейнера ссылается именно туда.

api и web собираются из одного Dockerfile и делят один тег apistend:local. Роль выбирается аргументом команды (api или web) в deploy/docker-entrypoint.sh — второй проход сборки берётся из кеша целиком.

Порядок старта

Контейнеры ждут друг друга, поэтому первый up занимает больше времени, чем кажется по выводу:

  1. 1

    База поднимается и проходит проверку pg_isready

    Проверка идёт каждые 5 секунд, до 10 попыток.

  2. 2

    api стартует после того, как база стала healthy

    Точка входа делает три вещи по порядку: prisma migrate deploy, затем сид на пустой базе, затем запуск сервера.

  3. 3

    web стартует после того, как api ответил на /health

    Проверка api — curl -fs http://127.0.0.1:8080/health, интервал 10 секунд, до 12 попыток, с отсрочкой первой проверки на 40 секунд.

Проверить, что шлюз ответил:

curl -s localhost:8080/health

Демо-аккаунт

Сид отрабатывает только на пустой базе: deploy/docker-entrypoint.sh запускает prisma/seed-if-empty.ts, а тот считает пользователей и на непустой базе не делает ничего. Перезапуск контейнера не затирает то, что вы успели наделать в кабинете.

Вход в кабинет на http://localhost:3100:

Демо-учётная запись

ПолеЗначение
logindemo
парольapistend2026

Сид заводит песочницы, ключи, вебхуки и журнал запросов — те же данные, что нарисованы в макете кабинета. Отключается переменной APISTEND_SEED=0.

Демо-аккаунт — только для локального стенда

Пароль напечатан в публичном репозитории. На сервере, до которого можно достучаться не с вашей машины, ставьте APISTEND_SEED=0 и заводите учётную запись обычной регистрацией.

Остановка и данные

docker compose stop          # остановить, всё сохранить
docker compose down          # остановить и удалить контейнеры
docker compose down -v       # то же самое и удалить базу вместе с томом

Данные лежат в томе Docker, а не в каталоге репозитория. Имя тома складывается из имени проекта compose и имени тома в файле:

$ docker volume ls | grep pgdata
local     apistend_apistend-pgdata

docker compose down том не трогает — стенд поднимется с теми же данными. Удаляет его только -v.

Пересборка после правок

Образ собирается один раз. Правка исходников в него не попадает, пока образ не пересобран:

docker compose up --build

Если вы правите код постоянно, контейнеры для этого неудобны — смотрите разработку без контейнеров.

Подводные камни

Адрес API зашивается в кабинет при сборке. NEXT_PUBLIC_API_URL — аргумент сборки (build.args в docker-compose.yml), а не переменная рантайма: значение попадает в клиентский код. По умолчанию это http://localhost:8080. Публикуете стенд по другому адресу — пересоберите образ с другим значением, иначе браузер продолжит ходить на localhost.

localhost внутри контейнера — сам контейнер. Вебхук на http://localhost:3000 уйдёт в контейнер api, а не в ваше приложение на хосте. Для доставки на машину укажите host.docker.internal — или пользуйтесь apistend listen, туннель этим не ограничен: агент сам приходит к API по опубликованному порту.

WEBHOOK_ALLOW_PRIVATE_TARGETS: '1' стоит в compose намеренно. В образе NODE_ENV=production, а в этом режиме доставка на приватные адреса запрещена. Для локального стенда это как раз нужный сценарий, для общего сервера — нет; подробности в переменных окружения.

JWT_SECRET по умолчанию известен всем. Compose подставляет dev-only-change-me-…, если переменной нет в окружении или в .env рядом с docker-compose.yml. Для чего-то, кроме своей машины, задайте свой: JWT_SECRET=$(openssl rand -base64 32).