نشر Vercel + Docker
مع اكتمال تطوير MegaShop، يحتاج Charlie إلى نشره في بيئة الإنتاج. يقدم Vercel عملية نشر بسيطة لكن خيارات التخصيص محدودة، بينما يوفر Docker تحكمًا كاملاً لكنه يتضمن تكوينًا معقدًا. يحتاج Bob إلى حل نشر مرن وموثوق—استخدام Vercel للواجهة الأمامية وAPI، وDocker لقاعدة البيانات وRedis.
1. ما ستتعلمه
- نشر Vercel: بدون تكوين + إعداد Nitro + متغيرات البيئة
- نشر Docker: Dockerfile + بناء متعدد المراحل + docker-compose
- نشر Node.js: إعداد standalone + PM2
- استضافة ثابتة: Cloudflare Pages / Netlify / S3
- دليل عملي لنشر MegaShop في الإنتاج: Vercel + Docker Compose
2. قصة حقيقية لمهندس معماري
(1) نقطة الألم: القدرة على تشغيل بيئات الإنتاج محليًا
كان MegaShop الخاص بـ Charlie يعمل بشكل مثالي محليًا، لكن بعد نشره على الخادم—متغيرات البيئة مفقودة، قاعدة البيانات لا يمكن الاتصال بها، Redis لا يعمل، وهناك تعارضات في المنافذ. استغرق Bob خمس محاولات للنشر بنجاح، وواجه مشكلة مختلفة في كل مرة.
(2) حل Docker + Vercel
يحزم Docker بيئة التشغيل بالكامل، وينشر Vercel الواجهة الأمامية بدون تكوين:
# Vercel: نشر بدون تكوين
vercel --prod
# Docker: بناء مرة واحدة، تشغيل في أي مكان
docker compose up -d
(3) الفوائد: نشر بنقرة واحدة + بيئات متسقة
يستخدم Charlie git push لتفعيل نشر Vercel للواجهة الأمامية وDocker Compose لإدارة قاعدة البيانات وRedis وخدمات Nuxt، مما يضمن بيئة متسقة تمامًا.
3. النشر على Vercel
(1) شجرة قرارات النشر متعدد المنصات
flowchart TB
A[نشر تطبيق Nuxt 3] --> B{هل تحتاج SSR؟}
B -->|لا| C[استضافة ثابتة<br/>Cloudflare/Netlify/S3]
B -->|نعم| D{حجم الفريق؟}
D -->|صغير/متوسط| E[Vercel<br/>نشر بدون تكوين]
D -->|كبير/مؤسسي| F[Docker + Node.js<br/>تحكم كامل]
E --> G[API + الواجهة الأمامية على Vercel]
F --> H[Docker Compose<br/>Nuxt + PostgreSQL + Redis]
(1) ▶ مثال: النشر بدون تكوين على Vercel
# تثبيت Vercel CLI
npm i -g vercel
# النشر (يكشف تلقائيًا عن Nuxt 3)
vercel
# نشر الإنتاج
vercel --prod
الناتج:
# تم تنفيذ الأمر بنجاح
(2) ▶ مثال: تكوين Vercel في nuxt.config.ts
// nuxt.config.ts
export default defineNuxtConfig({
nitro: {
preset: 'vercel' // مكوّن تلقائيًا بواسطة Vercel
},
// متغيرات البيئة المعينة في لوحة تحكم Vercel
runtimeConfig: {
databaseUrl: process.env.DATABASE_URL,
redisUrl: process.env.REDIS_URL,
public: {
apiBase: process.env.API_BASE
}
}
})
الناتج:
// التنفيذ ناجح
(2) مزايا وعيوب نشر Vercel
| البُعد | Vercel | Docker |
|---|---|---|
| تعقيد التكوين | 🟢 بدون تكوين | 🔴 يتطلب كتابة Dockerfile |
| سرعة النشر | ⚡ 30 ثانية | 🟡 بناء 3-5 دقائق |
| التخصيص | 🔴 مقيد | 🟢 تحكم كامل |
| قاعدة البيانات | 🔴 يتطلب خدمة خارجية (Vercel Postgres) | 🟢 نشر محلي |
| التكلفة | ⚠️ فوترة حسب الطلب | 🟢 رسوم خادم ثابتة |
| التوسع | 🟢 تلقائي | 🟡 يدوي/K8s |
4. نشر Docker
(1) ▶ مثال: Dockerfile متعدد المراحل
# Dockerfile
# المرحلة 1: تثبيت التبعيات
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci
# المرحلة 2: البناء
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npx prisma generate
RUN npm run build
# المرحلة 3: الإنتاج
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
# نسخ الأصول المبنية
COPY --from=builder /app/.output ./.output
COPY --from=builder /app/prisma ./prisma
EXPOSE 3000
CMD ["node", ".output/server/index.mjs"]
الناتج:
// التنفيذ ناجح
(2) ▶ مثال: تنسيق Docker Compose
# docker-compose.yml
version: '3.8'
services:
# تطبيق Nuxt
web:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://megashop:megashop_pass@db:5432/megashop
- REDIS_URL=redis://redis:6379
- JWT_ACCESS_SECRET=${JWT_ACCESS_SECRET}
- JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET}
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
restart: unless-stopped
# قاعدة بيانات PostgreSQL
db:
image: postgres:16-alpine
environment:
- POSTGRES_USER=megashop
- POSTGRES_PASSWORD=megashop_pass
- POSTGRES_DB=megashop
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U megashop"]
interval: 5s
timeout: 5s
retries: 5
restart: unless-stopped
# تخزين مؤقت Redis
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
restart: unless-stopped
# وكيل عكسي Nginx
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- web
restart: unless-stopped
volumes:
postgres_data:
redis_data:
الناتج:
CONTAINER ID IMAGE STATUS PORTS
abc123 nginx:latest Up 2 hours 0.0.0.0:80->80/tcp
(3) ▶ مثال: تكوين وكيل عكسي Nginx
# nginx.conf
events {
worker_connections 1024;
}
http {
upstream nuxt {
server web:3000;
}
server {
listen 80;
server_name megashop.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name megashop.com;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
location / {
proxy_pass http://nuxt;
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;
}
# تخزين مؤقت للأصول الثابتة
location /_nuxt/ {
proxy_pass http://nuxt;
expires 1y;
add_header Cache-Control "public, immutable";
}
}
}
الناتج:
// التنفيذ ناجح
5. Node.js Standalone + PM2
(1) ▶ مثال: بناء إعداد Standalone
// nuxt.config.ts
export default defineNuxtConfig({
nitro: {
preset: 'node-server',
compressPublicAssets: true
}
})
الناتج:
// التنفيذ ناجح
# بناء خادم مستقل
npm run build
# المخرجات: .output/server/index.mjs
# تشغيل مباشر
node .output/server/index.mjs
(2) ▶ مثال: إدارة عمليات PM2
// ecosystem.config.js
module.exports = {
apps: [{
name: 'megashop',
script: '.output/server/index.mjs',
instances: 'max', // استخدام جميع أنوية المعالج
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 3000,
DATABASE_URL: 'postgresql://megashop:pass@localhost:5432/megashop',
REDIS_URL: 'redis://localhost:6379'
},
max_memory_restart: '1G',
error_file: './logs/error.log',
out_file: './logs/out.log',
merge_logs: true,
autorestart: true
}]
}
الناتج:
// التنفيذ ناجح
# البدء مع PM2
pm2 start ecosystem.config.js
# المراقبة
pm2 monit
# إعادة التحميل (بدون توقف)
pm2 reload megashop
# السجلات
pm2 logs megashop
(1) مقارنة خيارات النشر
| الحل | التعقيد | القابلية للإدارة | قابلية التوسع | القابلية للتطبيق |
|---|---|---|---|---|
| Vercel | 🟢 منخفض | 🔴 منخفض | 🟢 تلقائي | فرق صغيرة/متوسطة |
| Docker Compose | 🟡 متوسط | 🟢 عالي | 🟡 يدوي | فرق متوسطة/كبيرة |
| PM2 + Nginx | 🟡 متوسط | 🟢 عالي | 🟡 يدوي | نشر VPS |
| K8s | 🔴 عالي | 🟢 الأعلى | 🟢 تلقائي | نطاق واسع |
6. مثال شامل: نشر MegaShop للإنتاج
# ============================================
# نشر MegaShop للإنتاج
# Docker Compose + Nginx + PostgreSQL + Redis
# ============================================
# 1. الاستنساخ والتكوين
git clone https://github.com/megashop/megashop.git
cd megashop
cp .env.example .env
# تعديل .env بأسرار الإنتاج
# 2. البناء والبدء
docker compose up -d --build
# 3. تشغيل ترحيلات قاعدة البيانات
docker compose exec web npx prisma migrate deploy
# 4. بذر البيانات الأولية (المرة الأولى فقط)
docker compose exec web npx prisma db seed
# 5. التحقق
curl https://megashop.com/api/products?limit=5
# 6. المراقبة
docker compose logs -f web
❓ أسئلة شائعة
node-server يولّد مخرجات مستقلة (.output/server/index.mjs)، لا يتطلب node_modules، ويمكن تشغيله مباشرة.docker compose exec web npx prisma migrate deploy. أو أضف خطوات الترحيل إلى Dockerfile. للإنتاج، استخدم migrate deploy (الذي لا ينشئ ترحيلات جديدة، بل يطبق الترحيلات الموجودة فقط).📖 ملخص
- Vercel: نشر بدون تكوين، مثالي للفرق الصغيرة والمتوسطة، مع حل موحد لواجهة API والواجهة الأمامية
- استخدام البناء متعدد المراحل لـ Docker لتوليد صور محسّنة، واستخدام Docker Compose لتنسيق مجموعة الخدمات الكاملة
- وضع كتلة PM2 يتيح تشغيل عمليات متعددة وإعادة تحميل بدون توقف
- وكيل عكسي Nginx + SSL + تخزين مؤقت للموارد الثابتة
- يوصي MegaShop بـ Docker Compose: Nuxt + PostgreSQL + Redis + Nginx
📝 تمارين
- تمرين أساسي (الصعوبة: ⭐): نشر MegaShop على Vercel، وتكوين متغيرات البيئة، والتحقق من أن صفحات SSR تعمل بشكل صحيح.
- تمرين متقدم (الصعوبة: ⭐⭐): كتابة Dockerfile وdocker-compose.yml لإطلاق البيئة الكاملة (Nuxt + PostgreSQL + Redis) محليًا.
- تحدي (الصعوبة: ⭐⭐⭐): تنفيذ نشر إنتاج كامل باستخدام Docker Compose وNginx وSSL، وتكوين فحوصات الصحة وإعادة التشغيل التلقائية.
---|



