Denozordec 5f2b4e2d40
Docker images / prepare-release (push) Successful in 11s
Docker images / backend-test (push) Successful in 2m4s
Docker images / frontend-image (push) Successful in 3m10s
Docker images / updater-image (push) Successful in 42s
Docker images / backend-image (push) Successful in 2m29s
Docker images / notify-webhook (push) Skipped
Docker images / publish-release (push) Successful in 10s
feat(backups): replace button with checkbox for server selection in backup settings
Updated the BackupCreateSheet and BackupsSettings components to use checkboxes for selecting servers instead of buttons. This improves user interaction by allowing for easier selection and toggling of server states. The Checkbox component is now integrated for better accessibility and functionality.
2026-09-08 14:47:44 +07:00
2026-05-03 11:16:07 +07:00
2026-05-02 01:17:08 +07:00

MikrotikManager-3

Монорепозиторий веб-приложения для управления MikroTik: UI на Next.js, API на Fastify, общие Zod-контракты, сборка Docker-образов через Gitea Actions и автоматическое обновление контейнеров на сервере через sidecar updater.

Содержание

  1. Состав монорепозитория
  2. Архитектура
  3. Локальная разработка
  4. CI/CD (Gitea Actions)
  5. Прод-развёртывание Docker
  6. Сервис updater
  7. Первичная настройка сервера
  8. Эксплуатация и сопровождение
  9. Чеклист деплоя

Состав монорепозитория

Компонент Путь Стек Порт (runtime) Docker-образ
Frontend корень (app/, components/, lib/, …) Next.js 16.2.4 (App Router), React 19 3000 …-frontend
Backend backend/ Fastify 5, TypeScript ESM, PostgreSQL 18, Drizzle 8000 …-backend
Контракты packages/contracts/ Zod 4, @mmapp/contracts встраиваются в frontend/backend
Updater deploy/updater/ bash, docker:27-cli, curl, jq …-updater
Деплой deploy/docker-compose.yml Docker Compose
CI .gitea/workflows/docker.yml Gitea Actions, Buildx push в git.shx.one

Имена образов в registry для репозитория denozord/MikrotikManager-3:

  • git.shx.one/denozord/mikrotikmanager-backend
  • git.shx.one/denozord/mikrotikmanager-frontend
  • git.shx.one/denozord/mikrotikmanager-updater

Для другого owner/repo подставьте имя по правилу CI (см. CI/CD).

Архитектура

Общая схема

flowchart TB
  subgraph dev [Локальная разработка]
    Browser["Браузер"]
    NextDev["Next.js :3000"]
    FastifyDev["Fastify :8000"]
    PostgresDev["PostgreSQL 18"]
    Contracts["@mmapp/contracts"]
    Browser --> NextDev
    Browser -->|"fetch /api, CORS"| FastifyDev
    FastifyDev --> PostgresDev
    Contracts --> NextDev
    Contracts --> FastifyDev
  end

  subgraph ci [Gitea Actions]
    WF[".gitea/workflows/docker.yml"]
    WF --> Reg["git.shx.one registry"]
  end

  subgraph prod [Прод-сервер]
    FE["mmapp-frontend :3000"]
    BE["mmapp-backend :8000"]
    PG["mmapp-postgres"]
    DBVol["volume sqlite ETL /app/data"]
    UPD["mmapp-updater"]
    Sock["/var/run/docker.sock"]
    Reg --> FE
    Reg --> BE
    Reg --> UPD
    UPD --> Sock
    UPD --> FE
    UPD --> BE
    BE --> PG
    BE --> DBVol
    BrowserProd["Клиент"] --> FE
    BrowserProd -->|"live + backendUrl"| BE
  end

Frontend и backend

  • Браузер загружает UI с порта 3000.
  • Запросы к API выполняются напрямую с клиента (fetch) на URL бэкенда. Next.js rewrites/proxy не используются (next.config.ts — только output: "standalone").
  • URL бэкенда и режим данных (mock / live) хранятся в localStorage (routerlists:data-source, routerlists:backend-url); по умолчанию http://localhost:8000. Настройка — страница Настройки в UI (app/(main)/settings/page.tsx, провайдер lib/data-source.tsx).
  • Backend слушает 8000, отдаёт GET /health и маршруты под /api/…. CORS разрешён для одного origin — переменная CORS_ORIGIN (backend/src/config.ts, backend/src/index.ts).
  • Отдельно от UI-режима: NEXT_PUBLIC_API_MODE (mock по умолчанию, live для RouterOS REST) — lib/api-mock.ts; для работы с API приложения через бэкенд в проде достаточно режима live в UI и корректного backendUrl.

Общие контракты (packages/contracts)

  • npm workspaces: корень + packages/* + backend (package.json).
  • Пакет @mmapp/contracts: сборка tscdist/, exports ./servers, ./events, ./alerts.
  • При npm install выполняется postinstallnpm run build -w @mmapp/contracts.
  • Backend: валидация и типы в маршрутах; frontend: типы и разбор ответов в shared/api/.

Поток образов: CI → registry → сервер

sequenceDiagram
  participant Gitea
  participant Actions
  participant Registry
  participant Updater
  participant Backend
  participant Frontend

  Gitea->>Actions: push main / workflow_dispatch
  Actions->>Registry: push backend/frontend/updater :latest и :sha
  Actions-->>Gitea: optional DEPLOY_WEBHOOK_URL POST
  loop каждые POLL_INTERVAL_SECONDS
    Updater->>Registry: imagetools inspect digest
    alt digest изменился
      Updater->>Registry: docker pull
      Updater->>Backend: stop/rm/run из snapshot
      Updater->>Frontend: stop/rm/run из snapshot
      Updater->>Backend: HTTP health
      Updater->>Frontend: HTTP health
    end
  end
  • Триггер workflow: push в ветку main, ручной workflow_dispatch.
  • Параллельные jobs: backend-test (PostgreSQL 18), backend-image, frontend-image, updater-image; опционально notify-webhook после backend и frontend, если задан секрет DEPLOY_WEBHOOK_URL.
  • Теги на каждый успешный push: :latest и :<commit-sha>; платформа linux/amd64.
  • На сервере образы подтягиваются вручную (docker compose pull) и/или через updater (сравнение digest у тега из targets.json). Webhook CI не заменяет updater.

Зависимости в проде

Зависимость Реализация
PostgreSQL Контейнер mmapp-postgres (postgres:18-alpine). DATABASE_URL=postgres://mmapp:…@postgres:5432/mmapp.
SQLite (ETL) Файл mikrotik.db на томе /app/data (DATABASE_PATH=/app/data/mikrotik.db). При старте, пока нет маркера data_migration.sqlite_imported_at, backend импортирует sqlite в PG (ON CONFLICT / upsert). После успешного импорта повтор не копирует заново. Том PG18: mmapp-pgdata:/var/lib/postgresql (не .../data).
Docker socket Только у контейнера updater: /var/run/docker.sock — доступ к Docker API хоста (управление контейнерами, pull).

Локальная разработка

Требования

  • Node.js 22 (как в Dockerfile.frontend и backend/Dockerfile).
  • npm с workspaces; установка из корня: npm ci или npm install.
  • Для нативной сборки better-sqlite3 на Linux может понадобиться toolchain (python3, make, g++); в Docker-образе backend они уже ставятся (нужен только для одноразового boot-ETL из mikrotik.db).
  • Локально нужен PostgreSQL 18 (deploy/docker-compose.postgres.yml или DATABASE_URL).
  • Backend Docker-образ ставит только workspaces backend + contracts (без корневых Next/React deps); в production логи — JSON без pino-pretty.

Запуск

Два процесса (frontend и backend):

npm install
npm run dev
npm --prefix backend run dev
Сервис URL Проверка
Frontend http://localhost:3000 открыть в браузере
Backend http://localhost:8000 curl -fsS http://localhost:8000/health

Переменные окружения (разработка)

Backend — скопировать backend/.env.example в backend/.env:

Переменная По умолчанию Назначение
DATABASE_URL postgres://mmapp:[email protected]:5432/mmapp подключение к PostgreSQL
DATABASE_PATH ./mikrotik.db SQLite только для boot-ETL, если PG пустой
PORT 8000 порт Fastify
CORS_ORIGIN http://localhost:3000 origin фронтенда для CORS

Frontend — в репозитории нет корневого .env.example. Опционально .env.local:

Переменная По умолчанию Назначение
NEXT_PUBLIC_API_MODE mock live — вызовы RouterOS REST через lib/api-mock.ts

Режим live для API приложения и URL бэкенда задаются в UI (не через build-time env).

Контракты и БД в dev

npm run build -w @mmapp/contracts

Схема PostgreSQL накатывается при старте backend из backend/drizzle/0000_postgresql.sql. Опциональный ETL:

npm --prefix backend run db:migrate-from-sqlite

CI/CD (Gitea Actions)

Файл: .gitea/workflows/docker.yml (имя workflow: Docker images).

Job Build context Dockerfile Имя образа
backend-image .ci/docker/backend (staging в CI) backend/Dockerfile git.shx.one/<owner>/<stem>-backend
frontend-image .ci/docker/frontend Dockerfile.frontend git.shx.one/<owner>/<stem>-frontend
updater-image deploy/updater deploy/updater/Dockerfile git.shx.one/<owner>/<stem>-updater
  • <owner> — первая часть gitea.repository, lower case.
  • <stem> — имя репозитория lower case без суффикса -<цифры> в конце (например MikrotikManager-3mikrotikmanager).

Логин в registry в CI: gitea.actor + секрет ACTIONS_PAT.

Кэш Buildx: type=gha, отдельные scope backend, frontend, updater.

Опциональный job notify-webhook: POST JSON {"repository","sha","ref","version","tag","releaseUrl"} на URL из секрета DEPLOY_WEBHOOK_URL после успешной сборки backend и frontend и публикации релиза (updater в needs не входит).

Версионирование и релизы

  • Базовая версия: v1.0.0. Линия semver: 1.x.y (major 2.x вне scope).
  • Job prepare-release запускает .ci/scripts/compute-release.mjs: коммиты с последнего тега v*.*.*, bump по Conventional Commits.
  • feat / feat! / BREAKING CHANGE → minor (1.x.0); fix, chore, docs, refactor, style, test, build, ci → patch (1.0.x).
  • Если после последнего тега нет новых коммитов, релиз пропускается; Docker-образы при этом всё равно собираются и публикуются с :latest и :<sha>.
  • Первый релиз без тега v1.0.0 возможен автоматически: CI берёт историю HEAD, считает bump от 1.0.0 и создаёт тег (например v1.1.0 при feat:).
  • Job publish-release: annotated tag v1.2.3, Gitea Release на https://git.shx.one (markdown notes), образы с тегами :latest, :<sha>, :<semver>.
  • UI: версия в sidebar и страница /releases; manifest public/release-manifest.json (в CI подставляется из артефакта).
  • Bootstrap: один раз выставить 1.0.0 в workspace package.json и создать тег v1.0.0 на main перед первым автоматическим bump.
  • Сообщения коммитов: см. .cursor/rules/release-versioning.mdc; subject и body — на русском, префикс Conventional Commits — на английском.

Прод-развёртывание Docker

Эталон без reverse-proxy: deploy/docker-compose.yml (порты 3000 / 8000 на хост).

Стек с Traefik + HTTPS (Let's Encrypt DNS-01 / Cloudflare), по аналогии с CDNManager: deploy/docker-compose.traefik.yml + deploy/env.traefik.example. На сервере публикуются только :80/:443; frontend получает HTTPS, /api и /health проксируются на backend внутри сети mmapp. Домен по умолчанию: mm.shnt.top.

CDN Manager + MikrotikManager (один Traefik)

Полный стек: Traefik + cdn.shnt.top + mm.shnt.top в одном Compose.

Файл Назначение
deploy/docker-compose.cdn-mm.yml Traefik + CDN Manager + MM backend/frontend/updater
deploy/env.cdn-mm.example общий .env
mkdir -p /opt/cdn-mm/{data/cdn,data/mm,state,updater}
cp deploy/docker-compose.cdn-mm.yml /opt/cdn-mm/docker-compose.yml
cp deploy/env.cdn-mm.example /opt/cdn-mm/.env
cp deploy/updater/targets.json.example /opt/cdn-mm/updater/targets.json
# заполнить CF_DNS_API_TOKEN, CLOUDFLARE_API_TOKEN, AUTH_JWT_SECRET, CORS_ORIGIN, …
docker login git.shx.one
cd /opt/cdn-mm && docker compose pull && docker compose up -d
curl -fsS https://cdn.shnt.top/health
curl -fsS https://mm.shnt.top/health

Данные: ./data/cdn (CDN), ./data/mm (MM). Сеть Traefik: edge. Не запускайте параллельно standalone docker-compose.traefik.yml CDNManager или MM на тех же 80/443.

Если на сервере уже крутится CDNManager Traefik (cdnmanager-traefik, сеть cdnmanager) — не поднимайте второй Traefik. Варианты:

Способ Файл
Compose без своего Traefik deploy/docker-compose.traefik-cdn.yml
Plain docker CLI (скрипт) deploy/run-beside-cdn-traefik.sh

Frontend вешается в сеть cdnmanager с Traefik-labels; backend/updater остаются в mmapp. Сертификат для MM_DOMAIN выпускает уже работающий Traefik CDNManager (тот же letsencrypt / Cloudflare DNS-01).

# Compose (рекомендуется)
mkdir -p /opt/mmapp/{data,state,updater}
cp deploy/docker-compose.traefik-cdn.yml /opt/mmapp/docker-compose.yml
cp deploy/env.traefik.example /opt/mmapp/.env          # MM_DOMAIN + CORS_ORIGIN
cp deploy/updater/targets.json.example /opt/mmapp/updater/targets.json
cd /opt/mmapp && docker compose pull && docker compose up -d

# Или одной CLI-командой (скрипт сам сделает network/pull/run/connect):
curl -fsSL -o /tmp/run-beside-cdn-traefik.sh \
  https://git.shx.one/denozord/MikrotikManager/raw/branch/main/deploy/run-beside-cdn-traefik.sh
chmod +x /tmp/run-beside-cdn-traefik.sh
sudo MM_DOMAIN=mm.shnt.top CORS_ORIGIN=https://mm.shnt.top /tmp/run-beside-cdn-traefik.sh

DNS: A/AAAA для mm.shnt.top → IP VPS, Cloudflare DNS only. Проверка: curl -fsS https://mm.shnt.top/health.

SSO auth-portal: docs/integrate-auth-portal.md (app id mm).

Рабочий каталог для команд compose — deploy/ (или -f deploy/docker-compose.yml / -f deploy/docker-compose.traefik.yml / -f deploy/docker-compose.traefik-cdn.yml / -f deploy/docker-compose.cdn-mm.yml из корня).

Прод-контейнеры

Сервис container_name Образ (пример) Порты host:container Тома restart
postgres mmapp-postgres postgres:18-alpine нет (внутренняя сеть) mmapp-pgdata unless-stopped
backend mmapp-backend git.shx.one/denozord/mikrotikmanager-backend:latest 8000:8000 sqlite ETL → /app/data unless-stopped
frontend mmapp-frontend git.shx.one/denozord/mikrotikmanager-frontend:latest 3000:3000 unless-stopped
updater mmapp-updater git.shx.one/denozord/mikrotikmanager-updater:latest не публикуются docker.sock, updater-state/state, targets.json/etc/updater/targets.json:ro unless-stopped

Метки для updater на backend и frontend:

Метка Пример значения
mmapp.updater.managed true
mmapp.updater.target backend / frontend
mmapp.updater.image полное имя образа с тегом

Явной пользовательской сети в compose нет — используется сеть проекта Compose по умолчанию.

Переменные окружения (прод)

Backend (в образе заданы NODE_ENV=production, PORT=8000; в compose задают DATABASE_URL, DATABASE_PATH для ETL и CORS):

Переменная Источник в compose Назначение
CORS_ORIGIN ${CORS_ORIGIN:-http://localhost:3000} origin UI, с которого браузер вызывает API
DATABASE_URL postgres://mmapp:${POSTGRES_PASSWORD}@postgres:5432/mmapp PostgreSQL
DATABASE_PATH /app/data/mikrotik.db SQLite на томе для одноразового ETL
POSTGRES_PASSWORD обязателен пароль пользователя mmapp

Frontend (в образе: PORT=3000, HOSTNAME=0.0.0.0). URL API в образ не зашит — задаётся в браузере (режим live + URL бэкенда) вместе с CORS_ORIGIN на backend.

Updater:

Переменная По умолчанию Назначение
TARGETS_FILE /etc/updater/targets.json список целей
STATE_FILE /state/updater-state.json digest и ошибки
POLL_INTERVAL_SECONDS 300 пауза между циклами опроса
HEALTH_TIMEOUT_SECONDS 600 ожидание HTTP health (первый boot с ETL может занять минуты)
STOP_TIMEOUT_SECONDS 30 docker stop -t
REGISTRY git.shx.one registry для docker login
REGISTRY_USERNAME пусто логин (если заданы оба с паролем)
REGISTRY_PASSWORD пусто пароль registry

Docker Compose

docker login git.shx.one
export CORS_ORIGIN=http://<хост>:3000
export REGISTRY_USERNAME=<user>
export REGISTRY_PASSWORD=<token>

Скопировать и отредактировать конфиг updater (health URL должны быть достижимы из контейнера updater):

cp deploy/updater/targets.json.example deploy/updater/targets.json

В deploy/docker-compose.yml для updater заменить bind-mount на рабочий файл:

- ./updater/targets.json:/etc/updater/targets.json:ro

Запуск:

cd deploy
docker compose pull
docker compose up -d

Эквивалентные docker run

Имена томов можно согласовать с compose (backend-data, updater-state) или задать явно.

Backend:

docker volume create backend-data
docker run -d \
  --name mmapp-backend \
  --restart unless-stopped \
  -p 8000:8000 \
  -e CORS_ORIGIN=http://localhost:3000 \
  -v backend-data:/app/data \
  --label mmapp.updater.managed=true \
  --label mmapp.updater.target=backend \
  --label mmapp.updater.image=git.shx.one/denozord/mikrotikmanager-backend:latest \
  git.shx.one/denozord/mikrotikmanager-backend:latest

Frontend:

docker run -d \
  --name mmapp-frontend \
  --restart unless-stopped \
  -p 3000:3000 \
  --label mmapp.updater.managed=true \
  --label mmapp.updater.target=frontend \
  --label mmapp.updater.image=git.shx.one/denozord/mikrotikmanager-frontend:latest \
  git.shx.one/denozord/mikrotikmanager-frontend:latest

Updater:

docker volume create updater-state
docker run -d \
  --name mmapp-updater \
  --restart unless-stopped \
  -e REGISTRY=git.shx.one \
  -e REGISTRY_USERNAME=<user> \
  -e REGISTRY_PASSWORD=<token> \
  -e POLL_INTERVAL_SECONDS=300 \
  -e HEALTH_TIMEOUT_SECONDS=120 \
  -e STOP_TIMEOUT_SECONDS=30 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v updater-state:/state \
  -v /path/to/targets.json:/etc/updater/targets.json:ro \
  git.shx.one/denozord/mikrotikmanager-updater:latest

Проверка после деплоя

Проверка Команда / ожидание
Backend health curl -fsS http://127.0.0.1:8000/health → JSON со status
Frontend curl -fsS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3000/200
Контейнеры docker ps --filter name=mmapp-
UI режим live, URL бэкенда совпадает с доступом клиента и с CORS_ORIGIN

Сервис updater

Исходники: deploy/updater/entrypoint.sh, образ deploy/updater/Dockerfile.

Назначение

Sidecar на хосте с Docker: периодически сравнивает digest манифеста образа в registry с последним применённым digest, при изменении выполняет docker pull, пересоздаёт целевой контейнер и проверяет HTTP health. Состояние — файл STATE_FILE (том updater-state).

Обнаружение новых образов

  • docker buildx imagetools inspect <image> → digest манифеста (тег в targets.json, обычно :latest).
  • Сравнение с last_applied_digest в state; при совпадении — noop.
  • При первом запуске — baseline из digest работающего контейнера или remote, чтобы не пересоздавать без смены digest.
  • Если remote digest недоступен — running контейнер не останавливается, в state пишется ошибка.

Перезапуск backend/frontend

Только контейнеры с метками mmapp.updater.managed=true, совпадающими mmapp.updater.target и mmapp.updater.image с записью в targets.json.

Последовательность: docker inspect (snapshot) → docker pulldocker stopdocker rmdocker run -d с восстановлением env, mounts, -p, --network, labels, restart policy из snapshot.

При неуспешном health после обновления — откат на previous_digest (image@digest). Если предыдущего digest нет — откат пропускается (лог rollback_skipped).

Конфигурация целей

Пример: deploy/updater/targets.json.example. Поля цели: id, container_name, image, health.type, health.url, health.expect_status.

Важно: в примере health URL — http://127.0.0.1:8000/health и http://127.0.0.1:3000/. В default bridge-сети контейнера updater 127.0.0.1 указывает на сам updater, а не на backend/frontend. Перед продом задайте URL, достижимые из контейнера updater (например опубликованные порты хоста при network_mode: host у updater, host.docker.internal с extra_hosts, или иной согласованный с вашей сетью вариант). Скопируйте example в deploy/updater/targets.json и отредактируйте.

Docker socket и безопасность

  • Монтирование /var/run/docker.sock даёт updater права на Docker API хоста: остановка, удаление и создание контейнеров, pull от имени хоста.
  • Ограничение по меткам снижает риск случайного пересоздания чужих контейнеров, но не изолирует updater от остального Docker на хосте.
  • Учётные данные registry передавайте через env, не коммитьте в git.
  • Блокировка цели: /state/locks/<target_id>; при занятом lock цикл для цели пропускается.
  • При ошибке цикла пауза удваивается (2 × POLL_INTERVAL_SECONDS) с джиттером до +10%.

Валидация и staging

bash deploy/updater/validate.sh

Чеклист сценариев на staging: deploy/updater/test-staging.sh.

Первичная настройка сервера

Пошагово на чистом Linux-хосте с доступом в интернет и к git.shx.one.

  1. Установить Docker Engine и плагин Compose (официальная документация Docker для вашего дистрибутива).
  2. Проверить:
docker version
docker compose version
  1. Открыть входящие порты 3000 (frontend) и 8000 (backend) в firewall или настроить внешний доступ согласно вашей схеме (reverse proxy в репозитории не описан).
  2. Войти в registry:
docker login git.shx.one
  1. Получить файлы деплоя: клонировать репозиторий или скопировать каталог deploy/ и подготовить deploy/updater/targets.json.
  2. Задать переменные окружения для compose (CORS_ORIGIN, REGISTRY_USERNAME, REGISTRY_PASSWORD при приватных образах).
  3. Подтянуть образы и запустить стек:
cd deploy
docker compose pull
docker compose up -d
  1. Проверить health (см. таблицу выше) и логи updater:
docker logs mmapp-updater --tail 50
  1. В UI включить режим live и указать URL бэкенда, доступный браузеру пользователя; убедиться, что значение совпадает с CORS_ORIGIN на backend.

Эксплуатация и сопровождение

Автообновление

Updater опрашивает registry с интервалом POLL_INTERVAL_SECONDS (по умолчанию 300 с). Обновление привязано к смене digest у образа из targets.json (часто тег :latest после push в main).

Ручное обновление

docker pull git.shx.one/denozord/mikrotikmanager-backend:latest
docker pull git.shx.one/denozord/mikrotikmanager-frontend:latest

Через compose (пересоздание при смене образа):

cd deploy
docker compose pull
docker compose up -d --force-recreate

Пинning версии: тег :<commit-sha> из CI вместо :latest в image, метке mmapp.updater.image и в targets.json.

Откат

  • Автоматически: updater при failed health после обновления — контейнер на previous_digest.
  • Вручную: остановить контейнер, запустить образ с нужным тегом или digest из registry, сохранив те же volume и labels. Откат схемы PostgreSQL updater не выполняет — нужен pg_dump / restore или том mmapp-pgdata.

Резервное копирование PostgreSQL

Том mmapp-pgdata и (до cleanup) sqlite mikrotik.db на /app/data. Из UI: Настройки → «Скачать бэкап» (pg_dump -Fc). С хоста:

docker exec mmapp-postgres pg_dump -Fc -U mmapp mmapp > mikrotik-manager.dump

Восстановление: UI «Восстановить из файла» или pg_restore --clean --if-exists -d ….

Том sqlite после успешного ETL и smoke не удаляйте сразу — оставьте как fallback, затем уберите mikrotik.db, когда маркер data_migration.sqlite_imported_at подтверждён.

Отладка

Действие Команда
Логи сервиса docker logs mmapp-backend, docker logs mmapp-frontend, docker logs mmapp-updater
Следить в реальном времени docker logs -f mmapp-updater
Конфигурация контейнера docker inspect mmapp-backend
Состояние updater том updater-state, файл /state/updater-state.json внутри контейнера

Чеклист деплоя

  1. Установить Docker Engine и Compose plugin; проверить docker version и docker compose version.
  2. Открыть порты 3000 и 8000 (или обеспечить доступ клиентов к UI и API).
  3. Выполнить docker login git.shx.one.
  4. Склонировать репозиторий или скопировать deploy/.
  5. Задать CORS_ORIGIN (origin фронтенда для браузера).
  6. Задать REGISTRY_USERNAME и REGISTRY_PASSWORD для updater при приватном registry.
  7. Создать deploy/updater/targets.json из example; настроить health URL для сети хоста.
  8. Обновить bind-mount targets в deploy/docker-compose.yml на ./updater/targets.json.
  9. Выполнить docker compose pull и docker compose up -d в каталоге deploy.
  10. Проверить curl на :8000/health и :3000/.
  11. В UI: режим live и URL бэкенда; сверить с CORS_ORIGIN.
  12. Просмотреть docker logs mmapp-updater; настроить регулярный backup тома backend-data.
S
Description
No description provided
Readme
4.2 MiB
1.26.0
Latest
2026-09-08 16:31:42 +07:00
Languages
TypeScript 98.3%
Shell 0.7%
JavaScript 0.3%
CSS 0.3%
Python 0.3%