Практика: полный деплой
Собрали весь путь от кода до продакшена.
Подготовка проекта
package.json
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"typecheck": "tsc --noEmit",
"test": "vitest",
"test:e2e": "playwright test"
}
}
next.config.ts
const nextConfig = {
output: process.env.DOCKER ? 'standalone' : undefined,
images: {
remotePatterns: [
{ protocol: 'https', hostname: 'images.example.com' },
],
},
async headers() {
return [
{
source: '/(.*)',
headers: [
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
],
},
];
},
};
export default nextConfig;
Валидация env
// lib/env.ts
import { z } from 'zod';
const envSchema = z.object({
DATABASE_URL: z.string().url(),
AUTH_SECRET: z.string().min(32),
NEXT_PUBLIC_API_URL: z.string().url(),
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
});
export const env = envSchema.parse(process.env);
Путь через Vercel
1. Пуш на GitHub
git init
git add .
git commit -m "Initial"
git remote add origin git@github.com:user/repo.git
git push -u origin main
2. Импорт на Vercel
- vercel.com → New Project
- Импортируй репозиторий
- Vercel определит Next.js
- Добавь переменные окружения
- Deploy
3. Переменные
В Settings → Environment Variables:
DATABASE_URL=postgresql://...
AUTH_SECRET=<32+ символов>
NEXT_PUBLIC_API_URL=https://api.example.com
Разные для Production и Preview.
4. Домен
Settings → Domains → добавь example.com.
Настрой DNS у регистратора.
5. Автоматический деплой
Каждый пуш в main — деплой в production. PR — preview.
Путь через Docker + VPS
1. VPS
Hetzner, DigitalOcean, Vultr. Ubuntu 22.04.
2. Установка
# Docker
curl -fsSL https://get.docker.com | sh
# Nginx
sudo apt install nginx
# Certbot
sudo apt install certbot python3-certbot-nginx
3. Клонирование
cd /var/www
git clone git@github.com:user/repo.git my-app
cd my-app
4. .env.production
DATABASE_URL=postgresql://postgres:password@db:5432/myapp
AUTH_SECRET=<32+ символов>
NEXT_PUBLIC_API_URL=https://example.com
5. Docker Compose
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://postgres:password@db:5432/myapp
- AUTH_SECRET=${AUTH_SECRET}
- NEXT_PUBLIC_API_URL=https://example.com
depends_on:
- db
restart: unless-stopped
db:
image: postgres:16-alpine
environment:
- POSTGRES_PASSWORD=password
- POSTGRES_DB=myapp
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
volumes:
postgres_data:
6. Запуск
docker compose up -d --build
7. Миграции
docker compose exec app npx prisma migrate deploy
8. Nginx
/etc/nginx/sites-available/example.com:
server {
listen 80;
server_name example.com www.example.com;
location / {
proxy_pass http://localhost:3000;
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;
}
}
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
9. SSL
sudo certbot --nginx -d example.com -d www.example.com
10. CI/CD
.github/workflows/deploy.yml:
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /var/www/my-app
git pull
docker compose up -d --build
docker compose exec -T app npx prisma migrate deploy
Чек-лист релиза
- Тесты проходят
- Линтер без ошибок
- Типы проверены
- Сборка работает
- Переменные окружения настроены
- Секреты не в репозитории
- SSL работает
- Домен настроен
- Nginx reverse proxy
- Sentry подключён
- Health-check доступен
- Бэкапы БД
- Мониторинг
- Логи
Откат
Если что-то сломалось:
Vercel
Deployments → выбери предыдущий → Promote to Production.
Docker
docker compose down
git checkout <предыдущий-коммит>
docker compose up -d --build
База
psql -U roman myapp < backup.sql
Итоги
- Vercel — просто
- Docker + VPS — контроль
- CI/CD автоматизирует
- Nginx и SSL на сервере
- Чек-лист перед релизом
- План отката