انتقل إلى المقال

Velraانشر الوكالة

انشر الوكالة

ضع الموقع ولوحة التحكم وواجهة API على الإنترنت: Docker Compose على خادم واحد، أو تطبيق واحد لكل مضيف من Dockerfile، أو Node.js عادي.

لحزمة الحزمة الكاملة

ثلاث طرق للنشر

الطريقةمناسبة لـما تحتاجه
Docker Compose على خادم واحدخادم VPS تتحكم فيه، والتطبيقات الثلاثة معًاالحزمة الكاملة، وDocker على الخادم، وخادم وكيل عكسي لـ HTTPS
تطبيق واحد لكل مضيف، من Dockerfile الخاص بهRailway وRender وFly.io ومضيفات أخرى تبني من Dockerfileمجلد كل تطبيق؛ ووحدة تخزين أو MySQL وحاوية تخزين لواجهة API
Node.js عاديأي مضيف NodeNode.js 22 أو أحدث وYarn 4 على المضيف

مهما كانت الطريقة التي تختارها، يدمج الموقع ولوحة التحكم عنوان واجهة API في JavaScript عند بنائهما، لذلك ابنهما بالعناوين العامة وليس المحلية أبدًا.

Docker Compose على خادم واحد

انسخ مجلد الحزمة إلى الخادم وضع ملف .env بجانب docker-compose.yml يحوي العناوين العامة الثلاثة. تُبنى منها الأصول المسموح بها لواجهة API، وعنوان لوحة التحكم، وعناوين الصور، وعنوان واجهة API في الواجهتين الأماميتين.

.env بجانب docker-compose.yml
SITE_URL=https://www.your-agency.com
ADMIN_URL=https://admin.your-agency.com
API_URL=https://api.your-agency.com
MEDIA_HOSTNAME=api.your-agency.com

MEDIA_HOSTNAME اختياري، مضيف واحد أو عدة مضيفات مفصولة بفواصل (أضف مضيف حاوية التخزين عندما تذهب الملفات المرفوعة إليها): تُغيَّر أحجام الصور على مضيفات https هذه بواسطة Next.js، وتُحمَّل أي صورة أخرى كما هي. ثم ابنِ وشغّل في الخلفية:

الطرفية
docker compose up --build -d
  • وجّه كل نطاق إلى الخادم عبر خادم وكيل عكسي يقدّم HTTPS (Caddy أو Nginx أو Traefik)، ويحوّل إلى المنافذ 3030 و3031 و8000.
  • خلف ذلك الوكيل، اضبط TRUST_PROXY=1 في back-end/.env، لتحسب حدود تسجيل الدخول ونموذج التواصل وطلب المعاينة كل زائر على حدة وليس الوكيل. تقرأ حاوية واجهة API الملف back-end/.env عند وجوده، وهناك أيضًا تُوضع المفاتيح الاختيارية.
  • بدون JWT_SECRET خاص بك، تولّد واجهة API واحدًا عند أول تشغيل وتحفظه في وحدة التخزين velra-data. وقاعدة البيانات والملفات المرفوعة في وحدة التخزين نفسها أيضًا، لذلك انسخها احتياطيًا.
  • يملأ التشغيل الأول الوكالة التجريبية ما لم يكن SEED_DEMO_DATA=false في .env. أبقِه في التشغيل الأول: فالبيانات الأولية هي التي تنشئ الحسابات.

واجهة API من Dockerfile

وجّه المضيف إلى مجلد واجهة API (back-end/ في الحزمة الكاملة). تستمع الصورة على PORT (8000 ما لم يحدد المضيف غيره)، وتردّ على GET /api/health بمجرد أن تستجيب قاعدة بياناتها، وتحفظ SQLite والملفات المرفوعة في /data.

  • اربط وحدة تخزين دائمة بالمسار /data. بدونها يبدأ كل نشر على قاعدة بيانات فارغة.
  • اضبط CORS_ORIGIN على عنوانَي الموقع ولوحة التحكم (مفصولين بفاصلة)، وFRONTEND_URL على عنوان لوحة التحكم، وPUBLIC_MEDIA_URL على العنوان العام لواجهة API متبوعًا بـ /media.
  • اضبط SEED_DEMO_DATA=true في أول تشغيل على وحدة تخزين جديدة: القيمة الافتراضية للصورة هي false، وهي تنشئ الجداول بلا حسابات. ولا تُملأ قاعدة بيانات موجودة بالبيانات الأولية مرة أخرى أبدًا.
  • اضبط JWT_SECRET خاصًا بك، أو دع الحاوية تولّد واحدًا وتحفظه في /data/.jwt-secret.
  • اضبط TRUST_PROXY=1: فمنصة الاستضافة تضع وكيلًا أمام الحاوية.
  • على MySQL (DB_TYPE=mysql ومتغيرات DB_* الخمسة) لا تنشئ الحاوية الجداول. شغّل node dist/database/seeder.js (الوكالة التجريبية) أو node dist/database/sync-schema.js (جداول فارغة) مرة واحدة بالبيئة نفسها.
  • تبقى الملفات المرفوعة على وحدة التخزين بعد إعادة النشر؛ ولإبعادها عن الخادم اضبط متغيرات R2_* الخمسة لحاوية تخزين.

الموقع ولوحة التحكم من Dockerfile الخاص بكل منهما

وجّه المضيف إلى مجلد التطبيق وأعطه قيم NEXT_PUBLIC_* على أنها معاملات بناء، وليس متغيرات تشغيل: فهي تُدمج عند البناء. تقدّم كل صورة خادم Next.js المستقل على PORT (3030 للموقع و3031 للوحة التحكم، ما لم يحدد المضيف غيرهما).

معامل البناءالتطبيقالقيمة
NEXT_PUBLIC_API_BASE_URLكلاهماالعنوان العام لواجهة API متبوعًا بـ /api
NEXT_PUBLIC_SITE_URLكلاهماالعنوان العام للموقع: الروابط الأساسية وخريطة الموقع في الموقع، ورابط «عرض الموقع» في لوحة التحكم
NEXT_PUBLIC_MEDIA_HOSTNAMEكلاهمااختياري. مضيفات https التي تقدّم الصور (نطاق واجهة API، أو نطاق حاوية التخزين، أو كلاهما)، مفصولة بفواصل
NEXT_PUBLIC_WEBSOCKET_BASE_URLلوحة التحكمالعنوان العام لواجهة API دون /api، للإشعارات المباشرة

يجلب خادم الموقع أيضًا من واجهة API أثناء عرض صفحات العقارات وخريطة الموقع. مع عنوان عام لواجهة API يعمل من الخادم أيضًا، لا يلزم شيء آخر؛ ويتغلب عليه API_INTERNAL_URL وقت التشغيل عندما يجب أن يستخدم الخادم عنوانًا آخر.

Node.js عادي

ابنِ كل تطبيق مرة واحدة على المضيف، ثم شغّله. اضبط .env الخاص بالواجهتين الأماميتين على العناوين العامة قبل yarn build.

التطبيقالبناءالتشغيل
APIyarn build، ثم مرة واحدة yarn seed:prod (الوكالة التجريبية) أو yarn db:sync:prod (جداول فارغة)yarn start:prod
الموقع العامyarn buildyarn start (المنفذ 3030)
لوحة تحكم الوكالةyarn buildyarn start (المنفذ 3031)

تربط واجهة API العنوان 0.0.0.0 وتقرأ PORT. أبقِ ملف SQLite وMEDIA_UPLOAD_DIR على تخزين يبقى بعد النشر، أو استخدم MySQL وحاوية تخزين.

حساباتك الأولى

لا توجد صفحة تسجيل: حسابا لوحة التحكم يأتيان من البيانات الأولية. ابدأ أول مرة بالوكالة التجريبية، وسجّل الدخول، ثم اجعلها لك:

  1. غيّر بيانات تسجيل الدخول للحسابين في الإعدادات ثم الأمان، أو أنشئ مديرًا عامًا (Super Admin) خاصًا بك في إدارة المسؤولين واحذف الحسابين الأوليين.
  2. أرشف العقارات التجريبية أو احذفها، واحذف الأحياء التجريبية التي لا تحتاج إليها.
  3. أغلق الاستفسارات التجريبية وألغِ المعاينات التجريبية: فلا يمكن حذفها.
  4. اضبط اسم الوكالة وعبارتها التعريفية ووصفها وبريد التواصل في الإعدادات ثم الوكالة، والمنازل المميزة في الصفحة الرئيسية في الإعدادات ثم الصفحة الرئيسية.

الإطلاق

قبل أن تصبح الوكالة متاحة من الإنترنت:

  1. في بيئة واجهة API، NODE_ENV=production وJWT_SECRET طويل وعشوائي خاص بك (يولّد Docker واحدًا عند عدم ضبطه). في الإنتاج ترفض واجهة API البدء بدون CORS_ORIGIN، وتذكر القيمة الناقصة.
  2. CORS_ORIGIN على عنوانَي الموقع ولوحة التحكم، وFRONTEND_URL على عنوان لوحة التحكم، وPUBLIC_MEDIA_URL على عنوان واجهة API متبوعًا بـ /media.
  3. قاعدة البيانات والملفات المرفوعة على تخزين دائم، مع نسخة احتياطية.
  4. فحص الصحة الخاص بالمضيف على /api/health، وTRUST_PROXY=1 خلف وكيل.
  5. بناء الواجهتين الأماميتين بقيم NEXT_PUBLIC_* العامة.
  6. في الموقع، علامتك التجارية في src/config/brand.config.ts، وسياسة الخصوصية في messages/privacy معاد كتابتها لوكالتك ولبلدك.
  7. تغيير بيانات تسجيل الدخول للحسابين الأوليين، أو حذفهما.
  8. DEMO_MODE=false على واجهة API وNEXT_PUBLIC_DEMO_MODE=false في الواجهتين الأماميتين، كما تُشحن.

ليس لوكالة لها بيانات حقيقية

يبني yarn setup:fresh ويحذف كل جدول ويملأ البيانات الأولية في كل مرة يُشغَّل فيها، ويحذف yarn db:reset كل جدول. يناسبان بيئة جديدة تمامًا، وليس أمر تشغيل أو بناء أبدًا.

توقفت عند خطوة؟

ابحث عن الحل قبل أن تبدأ من جديد.

حل المشكلات

تفضيلات ملفات تعريف الارتباط

نستخدم ملفات تعريف الارتباط لتعزيز تجربة التصفح الخاصة بك وتحليل حركة المرور على الموقع وتخصيص المحتوى. بالنقر على "قبول الكل"، فإنك توافق على استخدامنا لملفات تعريف الارتباط للتحليلات والإعلانات المخصصة.