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
214 lines
9.0 KiB
Markdown
214 lines
9.0 KiB
Markdown
# Docker Images
|
||
|
||
Образ собирается из [`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`
|
||
|
||
Замените `[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)
|
||
|
||
### Общие рекомендации
|
||
|
||
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 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>`)
|
||
|
||
```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 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 router-lists-ui && docker rm router-lists-ui
|
||
# затем снова docker run ... как выше
|
||
```
|
||
|
||
### v5
|
||
|
||
```bash
|
||
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`):
|
||
|
||
```yaml
|
||
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/…` сохраняется):
|
||
|
||
```nginx
|
||
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`
|
||
|
||
```bash
|
||
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
|
||
```
|
||
|
||
## Мониторинг
|
||
|
||
```bash
|
||
docker logs -f router-lists-ui
|
||
docker stats router-lists-ui
|
||
```
|
||
|
||
## Локальная сборка (как в CI)
|
||
|
||
```bash
|
||
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 network create router-lists-net
|
||
docker run -d --network router-lists-net ... git.shts.su/[repository]:latest
|
||
```
|
||
|
||
Ограничение ресурсов:
|
||
|
||
```bash
|
||
docker run -d --memory=512m --cpus=0.5 ... git.shts.su/[repository]:latest
|
||
```
|
||
|
||
## Устранение неполадок
|
||
|
||
```bash
|
||
docker ps -a --filter name=router-lists-ui
|
||
docker restart router-lists-ui
|
||
docker image prune -f
|
||
```
|
||
|
||
---
|
||
|
||
**Замените `[repository]`** на актуальный путь репозитория в Gitea (например `denozord/router-lists-ui`).
|