From a32f3420f9e31166cdeb1e3e4223adf21aafa81d Mon Sep 17 00:00:00 2001 From: Denozordec Date: Fri, 20 Mar 2026 23:24:32 +0700 Subject: [PATCH] Update README and server configuration for VPS Tracker application - Renamed project from "React + Vite" to "VPS Tracker" and updated the README to reflect the application's purpose and usage instructions. - Added detailed Docker setup instructions, including two methods for running the application: using Docker Compose and standalone Docker. - Implemented static file serving in the server configuration to serve the frontend from the 'dist' directory if it exists, enhancing the application's deployment capabilities. --- .dockerignore | 15 +++++ .github/workflows/docker.yml | 45 +++++++++++++++ Dockerfile | 20 +++++++ README.md | 103 ++++++++++++++++++++++++++++++++--- docker-compose.yml | 10 ++++ server/index.js | 14 +++++ 6 files changed, 198 insertions(+), 9 deletions(-) create mode 100644 .dockerignore create mode 100644 .github/workflows/docker.yml create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..88f725b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,15 @@ +node_modules +dist +data +.git +.github +.cursor +*.md +!README.md +.env +.env.* +!.env.example +coverage +*.log +.DS_Store +Thumbs.db diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..f8095e8 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,45 @@ +name: Docker + +on: + push: + branches: [main] + pull_request: + branches: [main] + +permissions: + contents: read + packages: write + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }} + tags: | + type=raw,value=latest,enable=${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + type=sha + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + push: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6dd82a9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +# syntax=docker/dockerfile:1 + +FROM node:22-alpine AS builder +WORKDIR /app +COPY package.json package-lock.json ./ +RUN npm ci +COPY index.html vite.config.js ./ +COPY public ./public +COPY src ./src +RUN npm run build + +FROM node:22-alpine AS runtime +WORKDIR /app +ENV NODE_ENV=production +COPY package.json package-lock.json ./ +RUN npm ci --omit=dev +COPY server ./server +COPY --from=builder /app/dist ./dist +EXPOSE 3001 +CMD ["node", "server/index.js"] diff --git a/README.md b/README.md index 18bc70e..7244c45 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,101 @@ -# React + Vite +# VPS Tracker -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. +Приложение для учёта виртуальных серверов (VPS), провайдеров, аккаунтов, платежей и балансов. Поддерживается синхронизация с BILLmanager 6 API. -Currently, two official plugins are available: +Ниже — основной сценарий запуска **в Docker**. Разработка без контейнера описана кратко в конце. Подробности по коду и доменам — в [AGENTS.md](AGENTS.md). -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh +--- -## React Compiler +## Запуск в Docker -The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). +### Требования -## Expanding the ESLint configuration +- [Docker](https://docs.docker.com/get-docker/) и [Docker Compose](https://docs.docker.com/compose/) v2 (`docker compose`). -If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project. +### Важно: база данных + +SQLite хранится в файле `data/vps-tracker.db` **внутри рабочей директории приложения** (`/app/data` в контейнере). Без **тома** (volume) при удалении или пересборке контейнера база пропадёт. Для постоянного хранения всегда монтируйте каталог на хосте в `/app/data`. + +### Вариант 1: Docker Compose (рекомендуется) + +В корне репозитория: + +```powershell +docker compose up --build +``` + +Откройте в браузере: **http://localhost:3001** (и API на том же хосте, префикс `/api/...`). + +Данные БД по умолчанию пишутся в `./data` на хосте (см. [docker-compose.yml](docker-compose.yml)). Каталог `data` можно создать заранее или он появится при первом запуске. + +Остановка: `Ctrl+C` или в другом окне: + +```powershell +docker compose down +``` + +### Вариант 2: только Docker (без Compose) + +Сборка образа: + +```powershell +docker build -t vps-tracker:local . +``` + +Запуск с томом для БД (пример для PowerShell — подставьте свой путь): + +```powershell +New-Item -ItemType Directory -Force -Path .\data | Out-Null +docker run --rm -p 3001:3001 -v "${PWD}\data:/app/data" vps-tracker:local +``` + +Снова открывайте **http://localhost:3001**. + +### Переменные окружения + +| Переменная | Описание | По умолчанию | +|------------|----------|--------------| +| `PORT` | Порт HTTP внутри контейнера | `3001` | + +При смене `PORT` пробросьте тот же порт наружу, например `-p 8080:8080` и `-e PORT=8080`. + +### Образ из GitHub Container Registry (GHCR) + +После push в ветку `main` workflow [.github/workflows/docker.yml](.github/workflows/docker.yml) собирает образ и публикует его в GHCR. + +1. На GitHub: **Packages** → пакет образа для этого репозитория (при необходимости сделайте пакет **public**, чтобы не требовалась авторизация для `docker pull`). +2. Имя образа: `ghcr.io/<владелец>/<репозиторий>:latest` (в GHCR имя образа задаётся в **нижнем** регистре). + +Пример (замените `OWNER` и `REPO`): + +```powershell +docker pull ghcr.io/OWNER/REPO:latest +New-Item -ItemType Directory -Force -Path .\data | Out-Null +docker run --rm -p 3001:3001 -v "${PWD}\data:/app/data" ghcr.io/OWNER/REPO:latest +``` + +Обновление: снова `docker pull ...:latest` и перезапуск контейнера. + +### CI/CD (кратко) + +- **Pull request** в `main`: в GitHub Actions выполняется только **сборка** образа (проверка, что Dockerfile валиден). +- **Push** в `main`: сборка и **push** в GHCR с тегами `latest` и SHA коммита. + +--- + +## Локальная разработка (без Docker) + +```powershell +npm install +npm run dev +``` + +Поднимаются Vite (фронт) и Express (API); API по умолчанию на порту **3001**, прокси настроен в [vite.config.js](vite.config.js). + +Сборка фронта отдельно: `npm run build`. Для проверки production-сборки на одном порту: после `npm run build` запустите `npm run server` — сервер отдаст статику из `dist`, если каталог существует. + +--- + +## Документация для разработчиков + +- [AGENTS.md](AGENTS.md) — структура репозитория, сущности, где искать sync, тарифы, API. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..608d900 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,10 @@ +# VPS Tracker: приложение + SQLite в ./data (создайте каталог или он появится при первом запуске) +services: + app: + build: . + ports: + - "3001:3001" + environment: + PORT: "3001" + volumes: + - ./data:/app/data diff --git a/server/index.js b/server/index.js index fdf0bfa..f17e36d 100644 --- a/server/index.js +++ b/server/index.js @@ -1,6 +1,12 @@ import express from 'express' import cors from 'cors' +import { existsSync } from 'fs' +import { dirname, join } from 'path' +import { fileURLToPath } from 'url' import { initDb } from './db.js' + +const __dirname = dirname(fileURLToPath(import.meta.url)) +const distPath = join(__dirname, '..', 'dist') import dataRouter from './routes/data.js' import migrateRouter from './routes/migrate.js' import vpsRouter from './routes/vps.js' @@ -34,6 +40,14 @@ app.use(express.json({ limit: '50mb' })) app.use('/api/projects', projectsRouter) app.use('/api/backup', backupRouter) + if (existsSync(distPath)) { + app.use(express.static(distPath)) + app.get(/.*/, (req, res, next) => { + if (req.path.startsWith('/api')) return next() + res.sendFile(join(distPath, 'index.html'), (err) => (err ? next(err) : undefined)) + }) + } + const { startScheduler } = await import('./sync-scheduler.js') startScheduler()