404 Not Found

404 Not Found


nginx

نشر Vercel + Docker

مع اكتمال تطوير MegaShop، يحتاج Charlie إلى نشره في بيئة الإنتاج. يقدم Vercel عملية نشر بسيطة لكن خيارات التخصيص محدودة، بينما يوفر Docker تحكمًا كاملاً لكنه يتضمن تكوينًا معقدًا. يحتاج Bob إلى حل نشر مرن وموثوق—استخدام Vercel للواجهة الأمامية وAPI، وDocker لقاعدة البيانات وRedis.

1. ما ستتعلمه


2. قصة حقيقية لمهندس معماري

(1) نقطة الألم: القدرة على تشغيل بيئات الإنتاج محليًا

كان MegaShop الخاص بـ Charlie يعمل بشكل مثالي محليًا، لكن بعد نشره على الخادم—متغيرات البيئة مفقودة، قاعدة البيانات لا يمكن الاتصال بها، Redis لا يعمل، وهناك تعارضات في المنافذ. استغرق Bob خمس محاولات للنشر بنجاح، وواجه مشكلة مختلفة في كل مرة.

(2) حل Docker + Vercel

يحزم Docker بيئة التشغيل بالكامل، وينشر Vercel الواجهة الأمامية بدون تكوين:

BASH
# Vercel: نشر بدون تكوين
vercel --prod

# Docker: بناء مرة واحدة، تشغيل في أي مكان
docker compose up -d

(3) الفوائد: نشر بنقرة واحدة + بيئات متسقة

يستخدم Charlie git push لتفعيل نشر Vercel للواجهة الأمامية وDocker Compose لإدارة قاعدة البيانات وRedis وخدمات Nuxt، مما يضمن بيئة متسقة تمامًا.


3. النشر على Vercel

(1) شجرة قرارات النشر متعدد المنصات

100%
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

BASH
# تثبيت Vercel CLI
npm i -g vercel

# النشر (يكشف تلقائيًا عن Nuxt 3)
vercel

# نشر الإنتاج
vercel --prod

الناتج:

TEXT
# تم تنفيذ الأمر بنجاح

(2) ▶ مثال: تكوين Vercel في nuxt.config.ts

TYPESCRIPT
// 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
    }
  }
})

الناتج:

TEXT
// التنفيذ ناجح

(2) مزايا وعيوب نشر Vercel

البُعد Vercel Docker
تعقيد التكوين 🟢 بدون تكوين 🔴 يتطلب كتابة Dockerfile
سرعة النشر ⚡ 30 ثانية 🟡 بناء 3-5 دقائق
التخصيص 🔴 مقيد 🟢 تحكم كامل
قاعدة البيانات 🔴 يتطلب خدمة خارجية (Vercel Postgres) 🟢 نشر محلي
التكلفة ⚠️ فوترة حسب الطلب 🟢 رسوم خادم ثابتة
التوسع 🟢 تلقائي 🟡 يدوي/K8s

4. نشر Docker

(1) ▶ مثال: Dockerfile متعدد المراحل

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"]

الناتج:

TEXT
// التنفيذ ناجح

(2) ▶ مثال: تنسيق Docker Compose

YAML
# 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:

الناتج:

TEXT
CONTAINER ID   IMAGE          STATUS         PORTS
abc123         nginx:latest   Up 2 hours     0.0.0.0:80->80/tcp

(3) ▶ مثال: تكوين وكيل عكسي Nginx

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";
        }
    }
}

الناتج:

TEXT
// التنفيذ ناجح

5. Node.js Standalone + PM2

(1) ▶ مثال: بناء إعداد Standalone

TYPESCRIPT
// nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    preset: 'node-server',
    compressPublicAssets: true
  }
})

الناتج:

TEXT
// التنفيذ ناجح
BASH
# بناء خادم مستقل
npm run build

# المخرجات: .output/server/index.mjs
# تشغيل مباشر
node .output/server/index.mjs

(2) ▶ مثال: إدارة عمليات PM2

JAVASCRIPT
// 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
  }]
}

الناتج:

TEXT
// التنفيذ ناجح
BASH
# البدء مع PM2
pm2 start ecosystem.config.js

# المراقبة
pm2 monit

# إعادة التحميل (بدون توقف)
pm2 reload megashop

# السجلات
pm2 logs megashop

(1) مقارنة خيارات النشر

الحل التعقيد القابلية للإدارة قابلية التوسع القابلية للتطبيق
Vercel 🟢 منخفض 🔴 منخفض 🟢 تلقائي فرق صغيرة/متوسطة
Docker Compose 🟡 متوسط 🟢 عالي 🟡 يدوي فرق متوسطة/كبيرة
PM2 + Nginx 🟡 متوسط 🟢 عالي 🟡 يدوي نشر VPS
K8s 🔴 عالي 🟢 الأعلى 🟢 تلقائي نطاق واسع

6. مثال شامل: نشر MegaShop للإنتاج

BASH
# ============================================
# نشر 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

❓ أسئلة شائعة

س هل طبقة Vercel المجانية كافية؟
ج تتضمن الطبقة المجانية 100 غيغابايت من النطاق الترددي شهريًا و1000 ساعة استخدام بدون خادم. إصابات التخزين المؤقت ISR لمليون صفحة من MegaShop لا تُحسب كاستدعاءات دالة، لذا فإن الطبقة المجانية كافية لحركة متوسطة.
س ما فوائد البناء متعدد المراحل لـ Docker؟
ج الصورة النهائية تحتوي فقط على الملفات الضرورية وقت التشغيل وتستبعد الكود المصدري وdevDependencies. حجم الصورة ينخفض من أكثر من 1 غيغابايت إلى حوالي 150 ميغابايت، مما يجعلها أكثر أمانًا وأسرع.
س ما الفرق بين Nuxt standalone وإعداد Node؟
ج لا يوجد فرق. إعداد node-server يولّد مخرجات مستقلة (.output/server/index.mjs)، لا يتطلب node_modules، ويمكن تشغيله مباشرة.
س هل يدعم وضع كتلة PM2 تقديم SSR؟
ج نعم. كل عامل عملية مستقلة تقدم SSR بنفسها. التخزين المؤقت ISR مشترك عبر Redis ويمكن لجميع العمال الوصول إليه.
س كيف أشغل ترحيلات Prisma في Docker؟
ج docker compose exec web npx prisma migrate deploy. أو أضف خطوات الترحيل إلى Dockerfile. للإنتاج، استخدم migrate deploy (الذي لا ينشئ ترحيلات جديدة، بل يطبق الترحيلات الموجودة فقط).
س كيف أحصل على شهادة SSL؟
ج لبيئات الإنتاج، استخدم Let's Encrypt + Certbot للتجديد التلقائي. لعمليات نشر Docker، استخدم nginx-proxy + acme-companion للحصول عليها تلقائيًا. يتضمن Vercel SSL افتراضيًا.

📖 ملخص


📝 تمارين

  1. تمرين أساسي (الصعوبة: ⭐): نشر MegaShop على Vercel، وتكوين متغيرات البيئة، والتحقق من أن صفحات SSR تعمل بشكل صحيح.
  2. تمرين متقدم (الصعوبة: ⭐⭐): كتابة Dockerfile وdocker-compose.yml لإطلاق البيئة الكاملة (Nuxt + PostgreSQL + Redis) محليًا.
  3. تحدي (الصعوبة: ⭐⭐⭐): تنفيذ نشر إنتاج كامل باستخدام Docker Compose وNginx وSSL، وتكوين فحوصات الصحة وإعادة التشغيل التلقائية.

---|

Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%