Update Docker documentation and README for SQLite storage and environment variables
Publish Docker image / build-and-push (push) Successful in 2m13s

- Enhanced Docker.md with detailed instructions on building and running Docker images, including environment variable requirements and tag usage.
- Updated README.md to reflect the current architecture using SQLite for data storage and clarified environment variable settings for backend and frontend operations.
- Removed references to AWS S3, emphasizing local storage for MikroTik backups and SQLite database management.

Made-with: Cursor
This commit is contained in:
2026-04-26 01:45:43 +07:00
parent 50f9c91843
commit cf3437c70c
2 changed files with 204 additions and 474 deletions
+128 -180
View File
@@ -1,118 +1,142 @@
# Docker Images
Этот проект предоставляет Docker образы для RouterOS Manager с двумя различными версиями интерфейса.
Образ собирается из [`Dockerfile.fast`](Dockerfile.fast) (многостадийная сборка: Vite frontend + `npm ci` backend, рантайм **distroless** Node 20). В Gitea Actions используется тот же файл (см. [`.gitea/workflows/docker-publish.yml`](.gitea/workflows/docker-publish.yml)).
## 🏷️ Доступные теги
## Теги в реестре `git.shts.su`
### Основная версия (main branch)
- `git.shts.su/[repository]:latest` - Стабильная версия с базовым интерфейсом
- `git.shts.su/[repository]:[commit-sha]` - Версия с конкретным коммитом
Замените `[repository]` на путь репозитория в Gitea (например `denozord/router-lists-ui`).
### Tabler версия (tabler branch)
- `git.shts.su/[repository]:tabler` - Версия с современным Tabler UI
- `git.shts.su/[repository]:tabler-[commit-sha]` - Tabler версия с конкретным коммитом
| Ветка (триггер push) | Образы в реестре |
|----------------------|-------------------|
| **main** (и v4, v3 и т.д. из workflow) | `git.shts.su/[repository]:latest` и `git.shts.su/[repository]:<полный-sha>` |
| **v5** | **только** `git.shts.su/[repository]:v5` и `git.shts.su/[repository]:v5-<полный-sha>` — тег **`latest` с ветки v5 не публикуется** |
| **tabler** | см. отдельный workflow `docker-publish-tabler.yml`, если включён |
## 🚀 Запуск
Пин на коммит: используйте тег с суффиксом `-<sha>`; «плавающий» тег ветки (`:v5` или `:latest`) всегда указывает на последнюю успешную сборку.
## Запуск (production)
### Общие рекомендации
1. **Данные на хосте** — смонтируйте том для SQLite и каталог бэкапов MikroTik, иначе при удалении контейнера пропадут БД и `.rsc`.
2. **Переменные** — минимум `ENCRYPTION_KEY`; для справочников и UI — `EVOBGP_API_URL` и `EVOBGP_API_TOKEN`; при необходимости `CORS_ORIGINS`, `PORT`.
3. **Рантайм distroless** — внутри образа **нет** `/bin/bash` и пакетного менеджера; отладка через `docker logs` / метрики. Интерактивная оболочка недоступна.
### Основная линия (`:latest`)
### Основная версия
```bash
docker run -d \
--name s3-lists-manager \
--name router-lists-ui \
-p 3001:3001 \
-e ENCRYPTION_KEY=your-64-hex-character-key-here \
-e ENCRYPTION_KEY=<64-hex> \
-e EVOBGP_API_URL=https://evobgp.example/v1 \
-e EVOBGP_API_TOKEN=<token> \
-e SQLITE_PATH=/data/router-lists.db \
-e MIKROTIK_BACKUP_DIR=/data/backups/mikrotik \
-v router-lists-data:/data \
git.shts.su/[repository]:latest
```
### Tabler версия
Каталог `/data` на томе должен быть доступен пользователю **nonroot** (образ distroless); при ошибках прав создайте том заранее или используйте bind-mount с `chown` под UID образа (обычно `65532` у nonroot).
### Ветка v5 (только теги `v5` / `v5-<sha>`)
```bash
docker pull git.shts.su/[repository]:v5
docker run -d \
--name router-lists-ui-v5 \
-p 3002:3001 \
-e ENCRYPTION_KEY=<64-hex> \
-e EVOBGP_API_URL=https://evobgp.example/v1 \
-e EVOBGP_API_TOKEN=<token> \
-e SQLITE_PATH=/data/router-lists.db \
-e MIKROTIK_BACKUP_DIR=/data/backups/mikrotik \
-v router-lists-v5-data:/data \
git.shts.su/[repository]:v5
```
Чтобы зафиксировать конкретный коммит:
```bash
docker run -d ... git.shts.su/[repository]:v5-1c6e6ab...
```
### Tabler-ветка (если публикуется отдельным workflow)
```bash
docker run -d \
--name s3-lists-manager-tabler \
-p 3001:3001 \
-e ENCRYPTION_KEY=your-64-hex-character-key-here \
--name router-lists-ui-tabler \
-p 3003:3001 \
--env-file ./backend/.env \
-v router-lists-tabler-data:/data \
git.shts.su/[repository]:tabler
```
## 🔄 Обновление
## Обновление образа
### latest
### Основная версия
```bash
docker pull git.shts.su/[repository]:latest
docker stop s3-lists-manager
docker rm s3-lists-manager
docker run -d \
--name s3-lists-manager \
-p 3001:3001 \
-e ENCRYPTION_KEY=your-64-hex-character-key-here \
git.shts.su/[repository]:latest
docker stop router-lists-ui && docker rm router-lists-ui
# затем снова docker run ... как выше
```
### Tabler версия
### v5
```bash
docker pull git.shts.su/[repository]:tabler
docker stop s3-lists-manager-tabler
docker rm s3-lists-manager-tabler
docker run -d \
--name s3-lists-manager-tabler \
-p 3001:3001 \
-e ENCRYPTION_KEY=your-64-hex-character-key-here \
git.shts.su/[repository]:tabler
docker pull git.shts.su/[repository]:v5
docker stop router-lists-ui-v5 && docker rm router-lists-ui-v5
docker run -d ... git.shts.su/[repository]:v5
```
## 🐳 Docker Compose
## Docker Compose
Создайте файл `docker-compose.yml`:
Пример **одной** службы на `latest` с томом данных (подставьте свой `image:` и при необходимости `env_file`):
```yaml
version: '3.8'
services:
s3-lists-manager:
router-lists-ui:
image: git.shts.su/[repository]:latest
container_name: s3-lists-manager
container_name: router-lists-ui
ports:
- "3001:3001"
restart: unless-stopped
environment:
- NODE_ENV=production
- ENCRYPTION_KEY=${ENCRYPTION_KEY} # Обязательно! Используйте .env файл или secrets
# Прокси EvoBGP для UI (Communities / Domains / …) — без CORS в браузере:
# - EVOBGP_API_URL=http://evobgp:8080
# - EVOBGP_API_TOKEN=...
NODE_ENV: production
ENCRYPTION_KEY: ${ENCRYPTION_KEY}
EVOBGP_API_URL: ${EVOBGP_API_URL}
EVOBGP_API_TOKEN: ${EVOBGP_API_TOKEN}
SQLITE_PATH: /data/router-lists.db
MIKROTIK_BACKUP_DIR: /data/backups/mikrotik
volumes:
- router-lists-data:/data
s3-lists-manager-tabler:
image: git.shts.su/[repository]:tabler
container_name: s3-lists-manager-tabler
ports:
- "3002:3001"
restart: unless-stopped
environment:
- NODE_ENV=production
- ENCRYPTION_KEY=${ENCRYPTION_KEY} # Обязательно! Используйте .env файл или secrets
volumes:
router-lists-data:
```
**Создайте файл `.env` в той же директории:**
```bash
ENCRYPTION_KEY=your-64-hex-character-key-here
```
Отдельный сервис для **v5** — тот же фрагмент, но `image: git.shts.su/[repository]:v5`, другой `container_name` и при желании отдельный volume.
Запуск:
```bash
docker-compose up -d
```
## Переменные окружения (контейнер)
## 🔧 Переменные окружения
| Переменная | Описание | Обязательная |
|------------|----------|----------------|
| `ENCRYPTION_KEY` | AES-256 для IPSec и паролей MikroTik (64 hex) | **Да** |
| `EVOBGP_API_URL` | Базовый URL API EvoBGP (серверный прокси `/api/evobgp` и бэкенд-справочники) | По сценарию |
| `EVOBGP_API_TOKEN` | Bearer к EvoBGP | По сценарию |
| `SQLITE_PATH` | Путь к файлу SQLite внутри контейнера (персистентный том) | Рекомендуется явно задать, напр. `/data/router-lists.db` |
| `MIKROTIK_BACKUP_DIR` | Каталог бэкапов `.rsc` на диске | Рекомендуется с томом, напр. `/data/backups/mikrotik` |
| `PORT` | Порт HTTP внутри контейнера | Нет (по умолчанию `3001`) |
| `CORS_ORIGINS` | Список Origin через запятую | Нет |
| `LOG_LEVEL` | Уровень логов pino | Нет |
| Переменная | Описание | По умолчанию | Обязательная |
|------------|----------|--------------|--------------|
| `NODE_ENV` | Окружение Node.js | `production` | Нет |
| `PORT` | Порт для запуска сервера | `3001` | Нет |
| `ENCRYPTION_KEY` | Ключ шифрования для IPSec паролей (64 hex символа) | - | **Да** |
| `EVOBGP_API_URL` | Базовый URL API EvoBGP для серверного прокси `/api/evobgp` (например `http://evobgp:8080` или `http://10.0.0.5:8080`; при необходимости к пути добавляется `/v1`) | - | Да, если используете интеграцию EvoBGP в UI |
| `EVOBGP_API_TOKEN` | Bearer-токен к API EvoBGP (только на сервере, не в браузере) | - | Да, если используете интеграцию EvoBGP в UI |
`ENCRYPTION_KEY` должен быть **один и тот же** между перезапусками, иначе не расшифровать уже сохранённые секреты.
### EvoBGP и reverse proxy (nginx)
Запросы UI идут на тот же origin: `/api/evobgp/…` обрабатывает **Node** внутри образа. Если перед приложением стоит **nginx**, нужно проксировать префикс `/api` на Node **без потери** сегмента `/api` в URI (иначе в upstream попадёт не тот путь и будет 404).
Запросы UI идут на тот же origin: `/api/evobgp/…` обрабатывает **Node** внутри образа. Если перед приложением стоит **nginx**, нужно проксировать префикс `/api` на Node **без потери** сегмента `/api` в URI.
**Рекомендуемый вариант** (путь `/api/…` сохраняется):
@@ -126,140 +150,64 @@ location /api/ {
}
```
**Типичная ошибка**: внутри `location /api` указать `proxy_pass http://127.0.0.1:3001/;` — nginx **срезает** `/api`, в Node приходит `/evobgp/router-lists/catalog` вместо `/api/evobgp/router-lists/catalog`. В коде добавлен запасной маршрут на `/evobgp`, но лучше поправить nginx.
**Типичная ошибка**: `proxy_pass http://127.0.0.1:3001/;` — nginx срезает `/api`. В коде есть запасной маршрут на `/evobgp`, но лучше исправить nginx.
**Проверка**: `GET http://<хост>:<порт>/api/evobgp` (без хвоста) должен вернуть JSON вида `{"ok":true,"proxy":true,"evobgpConfigured":true}` — если вместо этого HTML «404» или страница SPA, запрос **не доходит** до Node (только статика, другой порт или неверный `proxy_pass`).
**Проверка**: `GET http://<хост>:<порт>/api/evobgp` → JSON вида `{"ok":true,"proxy":true,"evobgpConfigured":true}`.
### ENCRYPTION_KEY
## Генерация `ENCRYPTION_KEY`
**Важно**: `ENCRYPTION_KEY` является обязательным параметром для работы с IPSec паролями. Этот ключ используется для шифрования/дешифрования паролей, хранящихся в S3.
**Генерация ключа:**
```bash
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
```
**Пример запуска с ENCRYPTION_KEY:**
## Мониторинг
```bash
docker run -d \
--name s3-lists-manager \
-p 3001:3001 \
-e ENCRYPTION_KEY=your-64-hex-character-key-here \
git.shts.su/[repository]:latest
docker logs -f router-lists-ui
docker stats router-lists-ui
```
**⚠️ Внимание**: Используйте один и тот же `ENCRYPTION_KEY` для всех запусков контейнера. При изменении ключа старые зашифрованные пароли не смогут быть расшифрованы.
## Локальная сборка (как в CI)
## 📊 Мониторинг
### Просмотр логов
```bash
# Основная версия
docker logs s3-lists-manager
# Tabler версия
docker logs s3-lists-manager-tabler
docker build -f Dockerfile.fast -t router-lists-ui:local .
docker run --rm -p 3001:3001 --env-file ./backend/.env -v $(pwd)/data:/data \
-e SQLITE_PATH=/data/router-lists.db \
-e MIKROTIK_BACKUP_DIR=/data/backups/mikrotik \
router-lists-ui:local
```
### Статистика контейнеров
(PowerShell на Windows: вместо `$(pwd)` используйте путь к каталогу данных.)
## CI/CD (Gitea Actions)
- [`.gitea/workflows/docker-publish.yml`](.gitea/workflows/docker-publish.yml) — пуш в перечисленные ветки (включая **v5**): сборка и push в `git.shts.su`.
- Для **v5** в реестр уходят **только** теги `v5` и `v5-<sha>` (без `latest`).
- Остальные ветки из списка workflow — `latest` и тег по SHA.
Шаг **Trigger container update webhook** (если задан `secrets.portainer_webhook`) выполняется после сборки; при ошибке шаг не валит job (`continue-on-error: true`).
## Безопасность и сеть
```bash
docker stats s3-lists-manager s3-lists-manager-tabler
docker network create router-lists-net
docker run -d --network router-lists-net ... git.shts.su/[repository]:latest
```
## 🔍 Отладка
Ограничение ресурсов:
### Вход в контейнер
```bash
# Основная версия
docker exec -it s3-lists-manager /bin/bash
# Tabler версия
docker exec -it s3-lists-manager-tabler /bin/bash
docker run -d --memory=512m --cpus=0.5 ... git.shts.su/[repository]:latest
```
### Проверка процессов
```bash
docker exec s3-lists-manager ps aux
```
## Устранение неполадок
## 🏗️ Сборка локально
### Основная версия
```bash
git checkout main
docker build -t s3-lists-manager:local .
```
### Tabler версия
```bash
git checkout tabler
docker build -t s3-lists-manager-tabler:local .
```
## 📝 CI/CD
### Автоматическая сборка
- **Ветка `main`**: Автоматически создает образ с тегом `latest`
- **Ветка `tabler`**: Автоматически создает образ с тегом `tabler`
### Workflow файлы
- `.gitea/workflows/docker-publish.yml` - Сборка основной версии
- `.gitea/workflows/docker-publish-tabler.yml` - Сборка Tabler версии
## 🔒 Безопасность
### Проверка образа
```bash
docker scan git.shts.su/[repository]:latest
docker scan git.shts.su/[repository]:tabler
```
### Запуск в изолированной сети
```bash
docker network create s3-lists-network
docker run -d \
--name s3-lists-manager \
--network s3-lists-network \
-p 3001:3001 \
git.shts.su/[repository]:latest
```
## 📈 Производительность
### Ограничение ресурсов
```bash
docker run -d \
--name s3-lists-manager \
--memory=512m \
--cpus=0.5 \
-p 3001:3001 \
git.shts.su/[repository]:latest
```
### Мониторинг ресурсов
```bash
docker stats --no-stream s3-lists-manager
```
## 🆘 Устранение неполадок
### Проверка статуса контейнера
```bash
docker ps -a | grep s3-lists-manager
```
### Перезапуск контейнера
```bash
docker restart s3-lists-manager
```
### Очистка неиспользуемых образов
```bash
docker ps -a --filter name=router-lists-ui
docker restart router-lists-ui
docker image prune -f
```
---
**Примечание**: Замените `[repository]` на актуальное имя вашего репозитория в Gitea.
**Замените `[repository]`** на актуальный путь репозитория в Gitea (например `denozord/router-lists-ui`).