feat: add Docker deployment (Dockerfile, docker-compose, .dockerignore) and update docs
- Multi-stage Dockerfile (node:22-slim, bun build, standalone output, non-root) - docker-compose.yml with DB volume, healthcheck, memory limits - .dockerignore to exclude dev artifacts from build context - docs: full deployment guide with docker compose, manual docker, env vars, reverse proxy configs (Caddy/Nginx), update instructions, server requirements - docs: comparison table old (Node.js bot) vs new (Next.js admin)
This commit is contained in:
27
.dockerignore
Normal file
27
.dockerignore
Normal file
@@ -0,0 +1,27 @@
|
||||
node_modules
|
||||
.next
|
||||
.git
|
||||
git
|
||||
*.md
|
||||
db/*.db
|
||||
db/*.db-journal
|
||||
tool-results/
|
||||
agent-ctx/
|
||||
.zscripts/
|
||||
screenshot-*.png
|
||||
keepalive.js
|
||||
seed-standalone.ts
|
||||
standalone-server.js
|
||||
gitea-*.json
|
||||
*.log
|
||||
dev.log
|
||||
server.log
|
||||
.env
|
||||
.dev
|
||||
tests/
|
||||
examples/
|
||||
mini-services/
|
||||
upload/
|
||||
download/
|
||||
Claude.md
|
||||
.claude
|
||||
59
Dockerfile
Normal file
59
Dockerfile
Normal file
@@ -0,0 +1,59 @@
|
||||
# --- Stage 1: Build ---
|
||||
FROM node:22-slim AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install bun for faster installs
|
||||
RUN npm install -g bun
|
||||
|
||||
# Install dependencies
|
||||
COPY package.json bun.lock ./
|
||||
RUN bun install --frozen-lockfile
|
||||
|
||||
# Copy source
|
||||
COPY prisma ./prisma/
|
||||
COPY tsconfig.json next.config.ts postcss.config.mjs tailwind.config.ts components.json ./
|
||||
COPY public ./public/
|
||||
COPY src ./src/
|
||||
|
||||
# Generate Prisma client
|
||||
RUN npx prisma generate
|
||||
|
||||
# Build Next.js (output: standalone)
|
||||
RUN npx next build
|
||||
|
||||
# Copy static assets into standalone
|
||||
RUN cp -r .next/static .next/standalone/.next/ && \
|
||||
cp -r public .next/standalone/
|
||||
|
||||
# --- Stage 2: Production ---
|
||||
FROM node:22-slim AS runner
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV=production
|
||||
ENV PORT=3000
|
||||
ENV HOSTNAME="0.0.0.0"
|
||||
|
||||
# Create non-root user
|
||||
RUN addgroup --system --gid 1001 nodejs && \
|
||||
adduser --system --uid 1001 nextjs
|
||||
|
||||
# Copy standalone output
|
||||
COPY --from=builder /app/.next/standalone ./
|
||||
|
||||
# Copy static files
|
||||
COPY --from=builder /app/.next/standalone/.next ./.next
|
||||
|
||||
# Copy Prisma schema for potential migrations
|
||||
COPY --from=builder /app/prisma ./prisma/
|
||||
|
||||
# Create db directory
|
||||
RUN mkdir -p /app/db && chown nextjs:nodejs /app/db
|
||||
|
||||
# Switch to non-root
|
||||
USER nextjs
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
CMD ["node", "server.js"]
|
||||
32
docker-compose.yml
Normal file
32
docker-compose.yml
Normal file
@@ -0,0 +1,32 @@
|
||||
services:
|
||||
admin:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./Dockerfile
|
||||
container_name: tg_shop_admin
|
||||
restart: always
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
# === Обязательные ===
|
||||
- DATABASE_URL=file:/app/db/custom.db
|
||||
- ADMIN_SECRET=${ADMIN_SECRET:-changeme}
|
||||
- SUPER_ADMIN_SECRET=${SUPER_ADMIN_SECRET:-changeme_super}
|
||||
# === ИИ-чатбот (опционально) ===
|
||||
- CHATBOT_API_KEY=${CHATBOT_API_KEY:-}
|
||||
- CHATBOT_API_ENDPOINT=${CHATBOT_API_ENDPOINT:-https://api.openai.com/v1}
|
||||
volumes:
|
||||
# Персистентная база данных
|
||||
- ./db:/app/db
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 512M
|
||||
reservations:
|
||||
memory: 256M
|
||||
healthcheck:
|
||||
test: ["CMD", "node", "-e", "const http = require('http'); http.get('http://localhost:3000/api/auth/session', r => { process.exit(r.statusCode === 401 ? 0 : 1) }).on('error', () => process.exit(1))"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 15s
|
||||
@@ -243,18 +243,162 @@ model Lead {
|
||||
- Оператор видит всю историю переписки
|
||||
- При отключении — бот снова отвечает
|
||||
|
||||
## Docker (ARM)
|
||||
## Развертывание (Docker)
|
||||
|
||||
### Сравнение со старой версией
|
||||
|
||||
| | Старая (Node.js бот) | Новая (Next.js админка) |
|
||||
|---|---|---|
|
||||
| Dockerfile | `FROM node:22`, `npm install`, `CMD node src/index.js` | Multi-stage build, standalone output, non-root user |
|
||||
| docker-compose | 1 сервис, BOT_TOKEN + ADMIN_IDS | 1 сервис, ADMIN_SECRET + CHATBOT_API_KEY |
|
||||
| БД | `./db/shop.db` (sqlite3 напрямую) | `./db/custom.db` (через Prisma ORM) |
|
||||
| Порт | Нет (только TG webhook) | 3000 (веб-интерфейс + API) |
|
||||
| RAM | ~64 MB | ~256–512 MB |
|
||||
|
||||
### Быстрый старт (docker compose)
|
||||
|
||||
```bash
|
||||
docker build -t tg-admin .
|
||||
docker run -p 3000:3000 -v ./db:/app/db \
|
||||
-e ADMIN_SECRET=your_secret \
|
||||
-e SUPER_ADMIN_SECRET=super_secret \
|
||||
-e CHATBOT_API_KEY=sk-xxx \
|
||||
tg-admin
|
||||
# 1. Клонировать ветку
|
||||
GIT_LFS_SKIP_SMUDGE=1 git clone -b feat/nextjs-admin https://git.softuniq.eu/Telegram-Market/telegram-shop.git
|
||||
CD telegram-shop
|
||||
|
||||
# 2. Создать .env файл
|
||||
cat > .env << 'EOF'
|
||||
ADMIN_SECRET=your_admin_password
|
||||
SUPER_ADMIN_SECRET=your_super_admin_password
|
||||
CHATBOT_API_KEY=sk-your-openai-key # опционально, для ИИ-бота
|
||||
CHATBOT_API_ENDPOINT=https://api.openai.com/v1 # или другой провайдер
|
||||
EOF
|
||||
|
||||
# 3. Создать папку для БД
|
||||
mkdir -p db
|
||||
|
||||
# 4. Собрать и запустить
|
||||
COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose up -d --build
|
||||
|
||||
# 5. Дождаться запуска (15-30 сек)
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
Требования: минимум 512 МБ RAM, ARM64/ARMv7/x86_64.
|
||||
После запуска админка доступна на `http://<IP>:3000`.
|
||||
|
||||
### Ручной Docker (без compose)
|
||||
|
||||
```bash
|
||||
# Сборка
|
||||
docker build -t tg-shop-admin .
|
||||
|
||||
# Запуск
|
||||
docker run -d \
|
||||
--name tg_shop_admin \
|
||||
--restart always \
|
||||
-p 3000:3000 \
|
||||
-v $(pwd)/db:/app/db \
|
||||
-e ADMIN_SECRET=your_admin_password \
|
||||
-e SUPER_ADMIN_SECRET=your_super_admin_password \
|
||||
-e CHATBOT_API_KEY=sk-xxx \
|
||||
-m 512m \
|
||||
tg-shop-admin
|
||||
```
|
||||
|
||||
### Переменные окружения
|
||||
|
||||
| Переменная | Обязательна | По умолчанию | Описание |
|
||||
|---|---|---|---|
|
||||
| `DATABASE_URL` | Нет | `file:/app/db/custom.db` | Путь к SQLite БД внутри контейнера |
|
||||
| `ADMIN_SECRET` | **Да** | `changeme` | Пароль для роли admin |
|
||||
| `SUPER_ADMIN_SECRET` | Нет | — | Пароль для роли super_admin |
|
||||
| `CHATBOT_API_KEY` | Нет | — | API-ключ для ИИ-бота (OpenAI/DeepSeek/etc) |
|
||||
| `CHATBOT_API_ENDPOINT` | Нет | `https://api.openai.com/v1` | Endpoint LLM-провайдера |
|
||||
|
||||
### Запуск без Docker (разработка)
|
||||
|
||||
```bash
|
||||
# Установить зависимости
|
||||
bun install
|
||||
|
||||
# Инициализация БД
|
||||
bun run db:push
|
||||
|
||||
# Создать .env
|
||||
echo 'DATABASE_URL=file:./db/custom.db' > .env
|
||||
echo 'ADMIN_SECRET=admin123' >> .env
|
||||
echo 'SUPER_ADMIN_SECRET=superadmin456' >> .env
|
||||
|
||||
# Генерация тестовых данных (опционально)
|
||||
curl -X POST http://localhost:3000/api/seed/demo \
|
||||
-H 'Cookie: admin_token=<your_token>'
|
||||
|
||||
# Dev-сервер
|
||||
bun run dev # http://localhost:3000
|
||||
|
||||
# Production
|
||||
bun run build # сборка standalone
|
||||
bun run start # запуск production
|
||||
```
|
||||
|
||||
### Первоначальная настройка после деплоя
|
||||
|
||||
1. Открыть `http://<IP>:3000`
|
||||
2. Войти с паролем из `ADMIN_SECRET`
|
||||
3. Перейти в **Settings** (`#/settings`) — настроить параметры магазина
|
||||
4. Перейти в **AI Chatbot** (`#/chatbot`) — настроить ИИ-бота:
|
||||
- Ввести API-ключ и выбрать провайдера
|
||||
- Настроить системный промпт
|
||||
- Добавить базу знаний (словарный лексикон)
|
||||
5. Перейти в **Danger Zone** → **Seed Demo Data** для заполнения тестовыми данными
|
||||
6. Очистить тестовые данные через **Clear Database** перед продакшеном
|
||||
|
||||
### Обновление
|
||||
|
||||
```bash
|
||||
# docker compose
|
||||
git pull
|
||||
docker compose up -d --build
|
||||
|
||||
# ручной
|
||||
git pull
|
||||
docker build -t tg-shop-admin .
|
||||
docker stop tg_shop_admin && docker rm tg_shop_admin
|
||||
# повторить docker run ...
|
||||
```
|
||||
|
||||
**Важно:** БД хранится в volume `./db`, она сохраняется при пересборке.
|
||||
|
||||
### Требования к серверу
|
||||
|
||||
| Ресурс | Минимум | Рекомендуется |
|
||||
|---|---|---|
|
||||
| CPU | 1 ядро | 2 ядра |
|
||||
| RAM | 256 MB | 512 MB |
|
||||
| Диск | 500 MB (образ) + БД | 1 GB |
|
||||
| Архитектура | x86_64, ARM64 | — |
|
||||
|
||||
### Reverse Proxy (Caddy / Nginx)
|
||||
|
||||
**Caddy** (авто HTTPS):
|
||||
```
|
||||
admin.yourdomain.com {
|
||||
reverse_proxy localhost:3000
|
||||
}
|
||||
```
|
||||
|
||||
**Nginx**:
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name admin.yourdomain.com;
|
||||
# ... ssl certs ...
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Seed-данные
|
||||
|
||||
|
||||
Reference in New Issue
Block a user