- 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
9.0 KiB
Docker Images
Образ собирается из Dockerfile.fast (многостадийная сборка: Vite frontend + npm ci backend, рантайм distroless Node 20). В Gitea Actions используется тот же файл (см. .gitea/workflows/docker-publish.yml).
Теги в реестре git.shts.su
Замените [repository] на путь репозитория в Gitea (например denozord/router-lists-ui).
| Ветка (триггер 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)
Общие рекомендации
- Данные на хосте — смонтируйте том для SQLite и каталог бэкапов MikroTik, иначе при удалении контейнера пропадут БД и
.rsc. - Переменные — минимум
ENCRYPTION_KEY; для справочников и UI —EVOBGP_API_URLиEVOBGP_API_TOKEN; при необходимостиCORS_ORIGINS,PORT. - Рантайм distroless — внутри образа нет
/bin/bashи пакетного менеджера; отладка черезdocker logs/ метрики. Интерактивная оболочка недоступна.
Основная линия (:latest)
docker run -d \
--name router-lists-ui \
-p 3001: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-data:/data \
git.shts.su/[repository]:latest
Каталог /data на томе должен быть доступен пользователю nonroot (образ distroless); при ошибках прав создайте том заранее или используйте bind-mount с chown под UID образа (обычно 65532 у nonroot).
Ветка v5 (только теги v5 / v5-<sha>)
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
Чтобы зафиксировать конкретный коммит:
docker run -d ... git.shts.su/[repository]:v5-1c6e6ab...
Tabler-ветка (если публикуется отдельным workflow)
docker run -d \
--name router-lists-ui-tabler \
-p 3003:3001 \
--env-file ./backend/.env \
-v router-lists-tabler-data:/data \
git.shts.su/[repository]:tabler
Обновление образа
latest
docker pull git.shts.su/[repository]:latest
docker stop router-lists-ui && docker rm router-lists-ui
# затем снова docker run ... как выше
v5
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
Пример одной службы на latest с томом данных (подставьте свой image: и при необходимости env_file):
services:
router-lists-ui:
image: git.shts.su/[repository]:latest
container_name: router-lists-ui
ports:
- "3001:3001"
restart: unless-stopped
environment:
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
volumes:
router-lists-data:
Отдельный сервис для v5 — тот же фрагмент, но image: git.shts.su/[repository]:v5, другой container_name и при желании отдельный volume.
Переменные окружения (контейнер)
| Переменная | Описание | Обязательная |
|---|---|---|
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 | Нет |
ENCRYPTION_KEY должен быть один и тот же между перезапусками, иначе не расшифровать уже сохранённые секреты.
EvoBGP и reverse proxy (nginx)
Запросы UI идут на тот же origin: /api/evobgp/… обрабатывает Node внутри образа. Если перед приложением стоит nginx, нужно проксировать префикс /api на Node без потери сегмента /api в URI.
Рекомендуемый вариант (путь /api/… сохраняется):
location /api/ {
proxy_pass http://127.0.0.1:3001/api/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Типичная ошибка: proxy_pass http://127.0.0.1:3001/; — nginx срезает /api. В коде есть запасной маршрут на /evobgp, но лучше исправить nginx.
Проверка: GET http://<хост>:<порт>/api/evobgp → JSON вида {"ok":true,"proxy":true,"evobgpConfigured":true}.
Генерация ENCRYPTION_KEY
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
Мониторинг
docker logs -f router-lists-ui
docker stats router-lists-ui
Локальная сборка (как в CI)
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— пуш в перечисленные ветки (включая 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).
Безопасность и сеть
docker network create router-lists-net
docker run -d --network router-lists-net ... git.shts.su/[repository]:latest
Ограничение ресурсов:
docker run -d --memory=512m --cpus=0.5 ... git.shts.su/[repository]:latest
Устранение неполадок
docker ps -a --filter name=router-lists-ui
docker restart router-lists-ui
docker image prune -f
Замените [repository] на актуальный путь репозитория в Gitea (например denozord/router-lists-ui).