Установка
Обновление и откат
Порядок действий при релизе, почему миграции необратимы и что делать после неудачного обновления.
На этой странице · 5
Обновление стенда — это код, схема базы и перезапуск процессов. Код и процессы возвращаются назад легко, схема — нет. С этого и начнём.
Миграции необратимы
prisma migrate deploy применяет неприменённые миграции и не умеет их отменять.
Обратных миграций в репозитории нет. Значит:
git revertвернёт код, но не схему. Старый код увидит новую схему и, если миграция что-то удалила или переименовала, сломается.- Единственный полный откат — восстановление дампа плюс выкатка того коммита, которому этот дамп соответствует.
- Миграцию, ломающую текущий код, разводите на два релиза: сначала совместимое изменение схемы, потом код, который на него опирается.
Дамп снимается до обновления, а не после
Восстановление из дампа возвращает базу в состояние на момент снимка. Всё, что произошло после, потеряно — это цена отката, и она тем меньше, чем свежее дамп.
Обновление в контейнерах
- 1
Снимите дамп
docker exec apistend-postgres pg_dump -U apistend -d apistend --format=custom \ > /var/backups/apistend-$(date +%F).pgdump - 2
Обновите код и пересоберите образ
git pull docker compose buildСборка идёт рядом с работающим стендом и его не трогает: старые контейнеры продолжают отвечать на старом образе.
- 3
Перезапустите
docker compose up -dКонтейнер
apiпри старте сам выполняетprisma migrate deploy, потом поднимает сервер.webдождётся, покаapiответит на/health. - 4
Проверьте
curl -s localhost:8080/healthИ зайдите в кабинет:
/healthне проверяет ни вход, ни отрисовку страниц.
Обновление из исходников
Порядок тот же, но шаги делаются руками и в строгой последовательности:
git pull
pnpm install --frozen-lockfile --prod=false
pnpm --filter @apistend/api exec prisma generate
pnpm --filter @apistend/api exec prisma migrate deploy
pnpm --filter @apistend/web run build
--prod=false обязателен: при NODE_ENV=production pnpm выбросит prisma и dotenv,
а dotenv импортируется в рантайме. Собирать API не нужно и нечем — он запускается
прямо с исходников через node --experimental-strip-types.
Кабинет и шлюз перезапускаются независимо. Мок-шлюз во время сборки кабинета продолжает отвечать, поэтому логичный порядок — собрать кабинет, потом перезапустить оба.
Если релиз не удался
- 1
Миграция упала
Схема осталась в промежуточном состоянии, а
apiне стартовал: точка входа работает сset -e, и сервер после неудачной миграции не запускается. Кабинет тоже не поднимется — он ждёт здоровьяapi. Разбирайтесь с миграцией на месте; молча пропускать её нельзя. - 2
Миграция прошла, а код сломался
Верните предыдущий коммит и пересоберите. Схема останется новой — это работает, пока миграция была совместимой. Если нет, переходите к следующему шагу.
- 3
Нужен полный откат
Восстановите дамп и выкатите тот коммит, при котором он снят:
docker compose stop api web docker exec -i apistend-postgres pg_restore -U apistend -d apistend --clean --if-exists \ < /var/backups/apistend-2026-09-09.pgdump git checkout <коммит> docker compose up -d --build
Что не переживает перезапуск
- Серии событий. Расписание живёт в памяти процесса. При старте незавершённые серии помечаются прерванными — оставить их в состоянии «идёт» значило бы показывать в интерфейсе неправду.
- Сессии туннеля.
apistend listenпридётся запустить заново. - Кеши. Кеш тел ответов и кеш разбора ключей прогреваются заново; первые запросы после рестарта медленнее.
Журнал запросов и приращения счётчиков ключей при этом не теряются: на SIGINT
и SIGTERM сервер дописывает накопленные буферы и только потом закрывается.
Убийство процесса по SIGKILL этой гарантии не даёт.