Production развертывание
Руководство по развертыванию DocAI в production окружении.
Требования
- Linux сервер (Ubuntu 22.04 рекомендуется)
- Docker 20.10+
- Docker Compose 2.0+
- 4GB RAM минимум (8GB рекомендуется)
- Nginx или другой reverse proxy
- SSL сертификат
Подготовка
1. Настройка переменных окружения
# Production настройки backend
cat > .env.backend << EOF
SECRET_KEY=$(openssl rand -hex 32)
DEBUG=0
DATABASE_USER=postgres
DATABASE_PASSWORD=$(openssl rand -hex 16)
DATABASE_NAME=docai
DATABASE_HOST=db
DATABASE_PORT=5432
ALLOWED_HOSTS=api.yourdomain.com,localhost
OCR_URL_DOC=http://ocr:8080/api/ocr
DIFY_BASE_URL=https://dify.yourdomain.com
EOF
# Production настройки frontend
cat > .env.frontend << EOF
NEXTAUTH_SECRET=$(openssl rand -base64 32)
NEXTAUTH_URL=https://yourdomain.com
API_URL=http://api:8000
# Public URLs (accessible from browser)
NEXT_PUBLIC_API_URL=https://yourdomain.com
NEXT_PUBLIC_DOCS_URL=https://yourdomain.com/docs
EOF
2. Настройка Docker Compose для production
# docker-compose.prod.yaml
version: '3.8'
services:
db:
image: postgres:14
restart: always
environment:
POSTGRES_USER: ${DATABASE_USER}
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
POSTGRES_DB: ${DATABASE_NAME}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
restart: always
command: redis-server --appendonly yes
volumes:
- redis_data:/data
api:
build:
context: backend
dockerfile: Dockerfile.prod
restart: always
environment:
- DJANGO_SETTINGS_MODULE=api.settings_prod
volumes:
- static_volume:/app/staticfiles
- media_volume:/app/media
env_file:
- .env.backend
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
web:
build:
context: frontend
dockerfile: Dockerfile.prod
restart: always
env_file:
- .env.frontend
depends_on:
- api
celery-worker:
build:
context: backend
dockerfile: Dockerfile.prod
restart: always
command: celery -A api worker --loglevel=warning --concurrency=2
volumes:
- media_volume:/app/media
env_file:
- .env.backend
depends_on:
- db
- redis
celery-beat:
build:
context: backend
dockerfile: Dockerfile.prod
restart: always
command: celery -A api beat --loglevel=warning
env_file:
- .env.backend
depends_on:
- db
- redis
docusaurus:
build:
context: docs
target: serve
args:
- NODE_ENV=production
restart: always
expose:
- "3000"
nginx:
image: nginx:alpine
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./docker/ssl:/etc/nginx/ssl:ro
- static_volume:/app/staticfiles:ro
- media_volume:/app/media:ro
depends_on:
- api
- web
- docusaurus
volumes:
postgres_data:
redis_data:
static_volume:
media_volume:
Nginx конфигурация
Полная конфигурация nginx находится в docker/nginx/nginx.conf. Основные настройки:
# nginx.conf
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
upstream api {
server api:8000;
}
upstream web {
server web:3000;
}
upstream docs {
server docusaurus:3000;
}
server {
listen 80;
server_name yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
client_max_body_size 100M;
# Frontend
location / {
proxy_pass http://web;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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;
proxy_cache_bypass $http_upgrade;
}
# Documentation (Docusaurus)
location /docs/ {
proxy_pass http://docs/;
proxy_http_version 1.1;
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;
}
# API
location /api/ {
proxy_pass http://api;
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;
proxy_read_timeout 300s;
}
location /documents/ {
proxy_pass http://api;
proxy_set_header Host $host;
client_max_body_size 100M;
proxy_read_timeout 300s;
}
location /ai_agents/ {
proxy_pass http://api;
proxy_set_header Host $host;
proxy_read_timeout 900s;
}
location /admin/ {
proxy_pass http://api;
proxy_set_header Host $host;
}
location /billing/ {
proxy_pass http://api;
proxy_set_header Host $host;
}
# Static files
location /static/ {
alias /app/staticfiles/;
expires 30d;
}
location /media/ {
alias /app/media/;
expires 7d;
}
}
}
Dockerfile для production
Backend
# backend/Dockerfile.prod
FROM python:3.13-slim
WORKDIR /app
RUN pip install uv
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev
COPY . .
RUN uv run -- python manage.py collectstatic --noinput
EXPOSE 8000
CMD ["uv", "run", "gunicorn", "api.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "4"]
Frontend
# frontend/Dockerfile.prod
FROM node:21-alpine AS builder
WORKDIR /app
RUN npm install -g pnpm
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY apps ./apps
COPY packages ./packages
RUN pnpm install --frozen-lockfile
RUN pnpm --filter web build
FROM node:21-alpine
WORKDIR /app
RUN npm install -g pnpm
COPY --from=builder /app/apps/web/.next/standalone ./
COPY --from=builder /app/apps/web/.next/static ./apps/web/.next/static
COPY --from=builder /app/apps/web/public ./apps/web/public
EXPOSE 3000
CMD ["node", "apps/web/server.js"]
Развертывание
# Сборка
docker compose -f docker-compose.prod.yaml build
# Миграции
docker compose -f docker-compose.prod.yaml run --rm api \
uv run -- python manage.py migrate
# Создание суперпользователя
docker compose -f docker-compose.prod.yaml run --rm api \
uv run -- python manage.py createsuperuser
# Запуск
docker compose -f docker-compose.prod.yaml up -d
Мониторинг
Логи
# Все логи
docker compose -f docker-compose.prod.yaml logs -f
# Конкретный сервис
docker compose -f docker-compose.prod.yaml logs -f api
Healthchecks
# Статус сервисов
docker compose -f docker-compose.prod.yaml ps
# Проверка API
curl -I https://yourdomain.com/api/schema/swagger-ui/
Бэкапы
База данных
# Создание бэкапа
docker compose -f docker-compose.prod.yaml exec db \
pg_dump -U postgres docai > backup_$(date +%Y%m%d).sql
# Восстановление
docker compose -f docker-compose.prod.yaml exec -T db \
psql -U postgres docai < backup_20241115.sql
Media файлы
# Бэкап
docker cp $(docker compose -f docker-compose.prod.yaml ps -q api):/app/media ./media_backup
# Восстановление
docker cp ./media_backup/. $(docker compose -f docker-compose.prod.yaml ps -q api):/app/media
Обновление
# Остановка
docker compose -f docker-compose.prod.yaml down
# Pull изменений
git pull origin main
# Пересборка
docker compose -f docker-compose.prod.yaml build
# Миграции
docker compose -f docker-compose.prod.yaml run --rm api \
uv run -- python manage.py migrate
# Запуск
docker compose -f docker-compose.prod.yaml up -d