Kamal 2: نشر تطبيق Next.js على VPS بدون توقف

AI Bot
بواسطة AI Bot ·

جاري تحميل مشغل تحويل النص إلى كلام الصوتي...

مقدمة

نشر تطبيق ويب في بيئة الإنتاج لا يجب أن يتطلب مجموعة Kubernetes أو مهندس DevOps مخصص أو فاتورة سحابية بأرقام كبيرة. ومع ذلك، في عام 2026، يجد العديد من المطورين أنفسهم محاصرين بين نقيضين: المنصات المُدارة المكلفة (Vercel، Railway) وتعقيد Kubernetes.

Kamal 2 هو إجابة 37signals (مبتكرو Ruby on Rails و Basecamp) على هذه المعضلة. كان يُعرف سابقاً باسم MRSK، وKamal هو أداة نشر مفتوحة المصدر تتيح لك نشر التطبيقات المُحاوية على أي خادم — VPS أو bare metal أو سحابي — مع صفر توقف وتراجع فوري وSSL تلقائي عبر Traefik.

ما يجعل Kamal 2 مميزاً بشكل خاص:

  • لا قيود على المزود — يعمل على أي خادم يدعم SSH و Docker
  • صفر توقف — يتم تشغيل الإصدارات الجديدة قبل إيقاف القديمة
  • تكوين بسيط — ملف YAML واحد (config/deploy.yml)
  • تراجع بأمر واحد — العودة للإصدار السابق فوراً
  • متعدد الخوادم — النشر على عدة أجهزة بالتوازي
  • دعم الملحقات — إدارة قواعد البيانات والخدمات المساعدة

في هذا الدليل التعليمي، ستتعلم:

  1. تثبيت وتكوين Kamal 2 على جهازك المحلي
  2. إعداد VPS للنشر
  3. حاوية تطبيق Next.js باستخدام Dockerfile محسّن
  4. تكوين Kamal للنشر بدون توقف
  5. إعداد SSL تلقائي مع Traefik
  6. النشر والمراقبة والتراجع

المتطلبات الأساسية

قبل البدء، تأكد من توفر:

  • خادم VPS بذاكرة 1 جيجابايت على الأقل و 1 vCPU (DigitalOcean، Hetzner، OVH، Contabo، إلخ.)
  • Ubuntu 22.04 أو 24.04 مثبت على الخادم
  • اسم نطاق يشير إلى خادمك (سجل DNS A)
  • Docker مثبت محلياً (لبناء الصور)
  • Ruby 3.1+ مثبت محلياً (Kamal مكتوب بـ Ruby)
  • تطبيق Next.js جاهز للنشر
  • حساب Docker Hub (أو سجل حاويات آخر)
  • معرفة أساسية بـ سطر أوامر Linux و Docker

ما ستبنيه

بنهاية هذا الدليل، سيكون لديك بنية نشر كاملة:

  • خادم VPS مُعَد تلقائياً بواسطة Kamal
  • تطبيق Next.js في بيئة الإنتاج مع SSL
  • وكيل Traefik يدير التوجيه والشهادات
  • خط أنابيب نشر بدون توقف
  • القدرة على التراجع بأمر واحد

الخطوة 1: تثبيت Kamal 2

يتم توزيع Kamal كحزمة Ruby gem. قم بتثبيته عالمياً على جهاز التطوير:

gem install kamal

تحقق من أن Kamal مثبت بشكل صحيح:

kamal version

يجب أن ترى شيئاً مثل 2.4.0 أو إصدار أحدث.

إذا كنت تفضل عدم تثبيت Ruby، يمكنك استخدام Kamal عبر Docker:

alias kamal='docker run -it --rm -v "${PWD}:/workdir" -v "/run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock" -e SSH_AUTH_SOCK="/run/host-services/ssh-auth.sock" -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/basecamp/kamal:latest'

الخطوة 2: إعداد الخادم VPS

2.1 إنشاء الخادم

أنشئ خادم VPS من مزودك المفضل. لهذا الدليل، خادم بهذه المواصفات الدنيا يكفي:

الموردالحد الأدنىالموصى به
الذاكرة1 جيجابايت2 جيجابايت
المعالج1 vCPU2 vCPUs
التخزين20 جيجابايت SSD40 جيجابايت SSD
النظامUbuntu 22.04Ubuntu 24.04

2.2 تكوين DNS

وجّه نطاقك إلى الخادم:

Type: A
Name: app (أو @ للجذر)
Value: <عنوان_IP_خادمك>
TTL: 300

2.3 تكوين SSH

تأكد من أنه يمكنك الاتصال بالخادم عبر SSH باستخدام مفتاحك:

ssh root@your-server.com

يتصل Kamal عبر SSH لتكوين Docker ونشر الحاويات. يتولى تلقائياً تثبيت Docker على الخادم أثناء النشر الأول — لا حاجة لتثبيت أي شيء يدوياً.

الخطوة 3: إعداد تطبيق Next.js

3.1 إنشاء المشروع (إذا لزم الأمر)

إذا كنت تبدأ من الصفر:

npx create-next-app@latest my-kamal-app --typescript --tailwind --app
cd my-kamal-app

3.2 إنشاء Dockerfile

أنشئ Dockerfile محسّن للإنتاج في جذر المشروع:

# المرحلة 1: تثبيت التبعيات
FROM node:20-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production
 
# المرحلة 2: بناء التطبيق
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
 
ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production
 
RUN npm run build
 
# المرحلة 3: صورة الإنتاج
FROM node:20-alpine AS runner
WORKDIR /app
 
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
 
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
 
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
 
USER nextjs
 
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
 
CMD ["node", "server.js"]

3.3 تكوين Next.js لوضع Standalone

عدّل ملف next.config.js (أو next.config.ts) لتفعيل وضع standalone:

/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'standalone',
}
 
module.exports = nextConfig

وضع standalone يولّد خادم Node.js مستقل يتضمن فقط الملفات الضرورية، مما يقلل حجم صورة Docker بشكل كبير.

3.4 إضافة ملف .dockerignore

أنشئ ملف .dockerignore لتسريع عمليات البناء:

node_modules
.next
.git
.gitignore
*.md
docker-compose*.yml
.env*.local

الخطوة 4: تهيئة Kamal

4.1 توليد التكوين

من جذر مشروع Next.js:

kamal init

ينشئ هذا الأمر الملفات التالية:

config/
  deploy.yml      # التكوين الرئيسي
.kamal/
  secrets         # متغيرات البيئة السرية
.env              # متغيرات محلية (تُضاف إلى .gitignore)

4.2 تكوين deploy.yml

استبدل محتوى config/deploy.yml بـ:

service: my-nextjs-app
 
image: your-docker-hub-user/my-nextjs-app
 
servers:
  web:
    hosts:
      - your-server.com
    labels:
      traefik.http.routers.my-nextjs-app.rule: Host(`app.your-domain.com`)
      traefik.http.routers.my-nextjs-app.entrypoints: websecure
      traefik.http.routers.my-nextjs-app.tls.certresolver: letsencrypt
    options:
      network: kamal
 
proxy:
  ssl: true
  host: app.your-domain.com
 
registry:
  username: your-docker-hub-user
  password:
    - KAMAL_REGISTRY_PASSWORD
 
env:
  clear:
    NODE_ENV: production
    HOSTNAME: 0.0.0.0
  secret:
    - DATABASE_URL
 
builder:
  dockerfile: Dockerfile
  multiarch: false
 
healthcheck:
  path: /api/health
  port: 3000
  interval: 10
  max_attempts: 30

لنحلل الأقسام المهمة:

  • service: اسم تطبيقك (يُستخدم لتسمية الحاويات)
  • image: المسار الكامل لصورة Docker على السجل
  • servers: قائمة الخوادم المستهدفة مع تسميات Traefik للتوجيه
  • proxy: يفعّل SSL التلقائي عبر Traefik و kamal-proxy
  • registry: بيانات اعتماد سجل Docker
  • env: متغيرات البيئة (واضحة وسرية منفصلة)
  • healthcheck: يتحقق Kamal من استجابة تطبيقك قبل تبديل حركة المرور

4.3 تكوين الأسرار

حرّر ملف .kamal/secrets:

KAMAL_REGISTRY_PASSWORD=your-docker-hub-password
DATABASE_URL=postgresql://user:pass@db-host:5432/mydb

يجب ألا يُلتزم هذا الملف أبداً في Git. تحقق من أن .kamal/secrets موجود في .gitignore.

4.4 إنشاء نقطة فحص الصحة

يستخدم Kamal فحص الصحة للتحقق من جاهزية تطبيقك قبل تبديل حركة المرور. أنشئ نقطة نهاية API بسيطة:

// app/api/health/route.ts
import { NextResponse } from 'next/server'
 
export async function GET() {
  return NextResponse.json({
    status: 'ok',
    timestamp: new Date().toISOString(),
  })
}

الخطوة 5: فهم النشر بدون توقف

قبل إطلاق أول نشر، دعنا نفهم كيف يضمن Kamal 2 عدم التوقف:

تدفق النشر

1. بناء صورة Docker محلياً (أو في CI)
2. دفع الصورة إلى السجل
3. سحب الصورة على الخادم(الخوادم)
4. تشغيل الحاوية الجديدة
5. فحص الصحة: Kamal ينتظر استجابة /api/health بـ 200
6. kamal-proxy يبدّل حركة المرور إلى الحاوية الجديدة
7. إيقاف الحاوية القديمة بشكل أنيق

النقطة الأساسية هي الخطوة 6: حركة المرور تتبدّل فقط بعد نجاح الحاوية الجديدة في فحص الصحة. هذا يعني أن مستخدميك لن يروا أبداً خطأ 502 أو صفحة فارغة أثناء النشر.

kamal-proxy مقابل Traefik

يستخدم Kamal 2 kamal-proxy، وكيل عكسي خفيف تم تطويره خصيصاً لـ Kamal. يحل محل الاعتماد على Traefik للتوجيه الأساسي، رغم أن Traefik يبقى متاحاً كخيار للتكوينات المتقدمة (خدمات متعددة، وسيط، إلخ.).

يتولى kamal-proxy:

  • تبديل حركة المرور بين الحاوية القديمة والجديدة
  • إنهاء SSL مع Let's Encrypt
  • فحوصات الصحة التلقائية
  • تصريف الاتصالات الحالية

الخطوة 6: النشر الأول

6.1 تشغيل الإعداد الأولي

النشر الأول يتطلب خطوة إعداد تُكوّن Docker و kamal-proxy على الخادم:

kamal setup

ينفذ هذا الأمر العمليات التالية:

  1. الاتصال بالخادم عبر SSH
  2. تثبيت Docker (إذا لم يكن موجوداً)
  3. تثبيت kamal-proxy
  4. تسجيل الدخول إلى سجل Docker
  5. بناء ودفع الصورة
  6. سحب وتشغيل الحاوية
  7. تكوين SSL

سترى مخرجات تفصيلية لكل خطوة:

  INFO [f97da026] Running docker login ...
  INFO [f97da026] Finished in 1.337 seconds
  INFO Building image ...
  INFO Pushing image ...
  INFO [48716498] Running docker pull ...
  INFO [48716498] Finished in 8.234 seconds
  INFO [48716498] Running docker run ...
  INFO Waiting for healthy container ...
  INFO Container is healthy!

6.2 التحقق من النشر

بعد الانتهاء، تحقق من أن كل شيء يعمل:

# التحقق من الحاويات قيد التشغيل
kamal details
 
# عرض سجلات التطبيق
kamal app logs
 
# التحقق من حالة الوكيل
kamal proxy details

زُر https://app.your-domain.com — يجب أن يكون تطبيق Next.js متاحاً مع شهادة SSL صالحة.

الخطوة 7: عمليات النشر اللاحقة

لعمليات النشر اللاحقة، أمر واحد يكفي:

kamal deploy

هذا كل شيء. سيقوم Kamal بـ:

  1. بناء الصورة الجديدة
  2. دفعها إلى السجل
  3. سحبها على الخادم
  4. تشغيل الحاوية الجديدة
  5. التحقق من فحص الصحة
  6. تبديل حركة المرور
  7. إيقاف الحاوية القديمة

النشر بدون إعادة بناء الصورة

إذا كنت قد بنيت ودفعت الصورة مسبقاً (مثلاً في CI):

kamal deploy --skip-push

الخطوة 8: التراجع

أحد أكبر مزايا Kamal هو سهولة التراجع. إذا سبب النشر مشاكل:

# التراجع إلى إصدار سابق
kamal rollback [TAG_الإصدار]

لرؤية الإصدارات المتاحة:

kamal app containers

التراجع شبه فوري لأن الصورة السابقة موجودة بالفعل على الخادم. يعيد Kamal ببساطة تشغيل الحاوية القديمة ويبدّل حركة المرور.

الخطوة 9: إدارة الملحقات (قواعد البيانات، Redis، إلخ.)

يمكن لـ Kamal إدارة خدمات مساعدة تسمى accessories. أضفها في config/deploy.yml:

accessories:
  db:
    image: postgres:16-alpine
    host: your-server.com
    port: "5432:5432"
    env:
      clear:
        POSTGRES_DB: my_app
      secret:
        - POSTGRES_PASSWORD
    directories:
      - data:/var/lib/postgresql/data
    options:
      network: kamal
 
  redis:
    image: redis:7-alpine
    host: your-server.com
    port: "6379:6379"
    directories:
      - data:/data
    options:
      network: kamal

نشر الملحقات:

# نشر جميع الملحقات
kamal accessory boot all
 
# أو ملحق محدد
kamal accessory boot db

الملحقات دائمة — لا يتم إعادة تشغيلها أثناء نشر التطبيق الرئيسي.

الخطوة 10: النشر متعدد الخوادم

للتطبيقات ذات الحركة العالية، يمكنك النشر على عدة خوادم:

servers:
  web:
    hosts:
      - server-1.your-domain.com
      - server-2.your-domain.com
      - server-3.your-domain.com

ينشر Kamal على جميع الخوادم بالتوازي. مع موازن أحمال (مثل DigitalOcean Load Balancer أو DNS round-robin)، تحصل على توفر عالٍ بدون جهد إضافي.

أدوار الخادم

يمكنك تحديد أدوار مختلفة لخوادمك:

servers:
  web:
    hosts:
      - web-1.example.com
      - web-2.example.com
  worker:
    hosts:
      - worker-1.example.com
    cmd: npm run worker

الخطوة 11: التكامل مع CI/CD باستخدام GitHub Actions

أتمت النشر باستخدام GitHub Actions:

# .github/workflows/deploy.yml
name: Deploy
 
on:
  push:
    branches: [main]
 
concurrency:
  group: deploy
  cancel-in-progress: true
 
env:
  DOCKER_BUILDKIT: 1
 
jobs:
  deploy:
    runs-on: ubuntu-latest
    timeout-minutes: 20
 
    steps:
      - uses: actions/checkout@v4
 
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.3"
          bundler-cache: true
 
      - name: Install Kamal
        run: gem install kamal
 
      - name: Set up SSH
        uses: webfactory/ssh-agent@v0.9.0
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
 
      - name: Deploy with Kamal
        env:
          KAMAL_REGISTRY_PASSWORD: ${{ secrets.DOCKER_HUB_TOKEN }}
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
        run: kamal deploy

أضف الأسرار التالية في مستودع GitHub:

  • SSH_PRIVATE_KEY: مفتاح SSH الخاص بخادمك
  • DOCKER_HUB_TOKEN: رمز Docker Hub
  • DATABASE_URL: سلسلة اتصال قاعدة البيانات

الخطوة 12: الأوامر اليومية

إليك أوامر Kamal التي ستستخدمها أكثر:

إدارة التطبيق

# النشر
kamal deploy
 
# عرض السجلات مباشرة
kamal app logs -f
 
# تنفيذ أمر في الحاوية
kamal app exec "node -e 'console.log(process.env.NODE_ENV)'"
 
# فتح جلسة تفاعلية
kamal app exec -i bash
 
# إعادة تشغيل التطبيق
kamal app boot
 
# إيقاف التطبيق
kamal app stop

إدارة الوكيل

# عرض تكوين الوكيل
kamal proxy details
 
# إعادة تحميل التكوين
kamal proxy reboot

إدارة الملحقات

# عرض سجلات قاعدة البيانات
kamal accessory logs db
 
# إعادة تشغيل Redis
kamal accessory reboot redis
 
# تشغيل psql
kamal accessory exec db "psql -U postgres my_app"

الصيانة

# تنظيف صور Docker القديمة
kamal prune all
 
# قفل النشر (صيانة)
kamal lock acquire -m "صيانة جارية"
 
# فتح القفل
kamal lock release

الخطوة 13: مراقبة تطبيقك

فحص صحة متقدم

حسّن نقطة فحص الصحة للتحقق من التبعيات:

// app/api/health/route.ts
import { NextResponse } from 'next/server'
 
interface HealthStatus {
  status: string
  timestamp: string
  uptime: number
  checks: {
    database?: string
    memory?: {
      used: number
      total: number
    }
  }
}
 
export async function GET() {
  const health: HealthStatus = {
    status: 'ok',
    timestamp: new Date().toISOString(),
    uptime: process.uptime(),
    checks: {},
  }
 
  // التحقق من الذاكرة
  const memUsage = process.memoryUsage()
  health.checks.memory = {
    used: Math.round(memUsage.heapUsed / 1024 / 1024),
    total: Math.round(memUsage.heapTotal / 1024 / 1024),
  }
 
  return NextResponse.json(health)
}

المراقبة الخارجية

لمراقبة شاملة، يمكنك إضافة خدمة مراقبة كملحق:

accessories:
  uptime-kuma:
    image: louislam/uptime-kuma:1
    host: your-server.com
    port: "3001:3001"
    directories:
      - data:/app/data
    options:
      network: kamal

استكشاف الأخطاء

فشل فحص الصحة

إذا فشل النشر بسبب انتهاء مهلة فحص الصحة:

  1. تحقق من سجلات الحاوية:

    kamal app logs
  2. اختبر فحص الصحة محلياً:

    docker build -t test-app .
    docker run -p 3000:3000 test-app
    curl http://localhost:3000/api/health
  3. زد المهلة في deploy.yml:

    healthcheck:
      max_attempts: 60
      interval: 5

خطأ صلاحية SSH

إذا لم يتمكن Kamal من الاتصال بالخادم:

# تحقق من تحميل مفتاحك
ssh-add -l
 
# أضف مفتاحك إذا لزم الأمر
ssh-add ~/.ssh/id_ed25519
 
# اختبر الاتصال
ssh root@your-server.com "echo OK"

الصورة كبيرة جداً

إذا استغرق البناء أو الدفع وقتاً طويلاً، حسّن Dockerfile:

  • استخدم البناء متعدد المراحل (تم بالفعل في Dockerfile الخاص بنا)
  • تحقق من .dockerignore
  • استخدم node:20-alpine بدلاً من node:20
  • فعّل BuildKit لتخزين الطبقات:
    export DOCKER_BUILDKIT=1

مشكلة شهادة SSL

إذا لم يعمل SSL:

  1. تحقق من أن DNS يشير إلى الخادم:

    dig app.your-domain.com
  2. تحقق من سجلات الوكيل:

    kamal proxy logs
  3. تأكد من فتح المنافذ 80 و 443 على جدار حماية الخادم.

Kamal مقابل البدائل

الميزةKamal 2CoolifyVercelKubernetes
صفر توقفنعمنعمنعمنعم
SSL تلقائينعمنعمنعممعقد
تراجعأمر واحدواجهةتلقائيمعقد
متعدد الخوادمنعمنعممُدارنعم
التكلفةVPS فقطVPS فقطحسب الاستخداممرتفع
التعقيدمنخفضمنخفضمنخفض جداًمرتفع جداً
قيود المزودلا يوجدمنخفضمرتفعمنخفض
واجهة ويبلانعمنعملوحة تحكم
CI/CD مدمجلا (عبر GH Actions)نعمنعملا

يتميز Kamal بـ بساطته و عدم وجود قيود على المزود. ملف YAML واحد، بضعة أوامر، وتطبيقك في بيئة الإنتاج. لا لوحة تحكم ويب للإدارة، لا خدمة سحابية للدفع — فقط SSH و Docker وخادمك.

الخطوات التالية

الآن بعد نشر تطبيقك باستخدام Kamal 2، إليك كيفية المضي قدماً:

  • أضف CDN مثل Cloudflare أمام خادمك لتحسين الأداء
  • أعد تنبيهات باستخدام Uptime Kuma أو Better Stack للإشعار بالمشاكل
  • أعد بيئة staging بملف تكوين ثانٍ (config/deploy.staging.yml)
  • أتمت النسخ الاحتياطي لقاعدة بياناتك بمهمة cron على الخادم
  • استكشف خطافات Kamal لتنفيذ سكربتات قبل/بعد النشر (ترحيل قاعدة البيانات، إبطال ذاكرة التخزين المؤقت، إلخ.)

الخلاصة

يمثل Kamal 2 نهجاً منعشاً في النشر: لا تعقيد غير ضروري، لا قيود على المزود، لا فواتير مفاجئة. مع خادم VPS بـ 5 يورو شهرياً وبضع دقائق من التكوين، تحصل على خط أنابيب نشر احترافي بدون توقف.

تتوافق فلسفة Kamal تماماً مع الحركة المتنامية نحو الاستضافة الذاتية والسيادة الرقمية. تحتفظ بالتحكم الكامل في بياناتك وبنيتك التحتية، مع الاستمتاع بتجربة مطور سلسة.

سواء كنت تنشر مشروعاً جانبياً أو شركة ناشئة أو تطبيق مؤسسة، يمنحك Kamal 2 القوة التي تحتاجها دون التعقيد غير الضروري. وإذا احتجت غداً لتغيير مزود الخادم، يكفي تعديل سطر واحد في ملف التكوين.


هل تريد قراءة المزيد من الدروس التعليمية؟ تحقق من أحدث درس تعليمي لدينا على كيفية فتح حساب Flouci المهني المجاني للعاملين لحسابهم الخاص في تونس.

ناقش مشروعك معنا

نحن هنا للمساعدة في احتياجات تطوير الويب الخاصة بك. حدد موعدًا لمناقشة مشروعك وكيف يمكننا مساعدتك.

دعنا نجد أفضل الحلول لاحتياجاتك.

مقالات ذات صلة

Docker Compose للمطورين: Next.js مع PostgreSQL و Redis

تعلم كيفية تغليف تطبيق Next.js كامل مع PostgreSQL و Redis باستخدام Docker Compose. يغطي هذا الدليل العملي تنسيق الخدمات المتعددة وسير عمل التطوير وإعادة التحميل الفوري وفحوصات الصحة والإعدادات الجاهزة للإنتاج.

28 د قراءة·