Skip to content
كل المقالاتنشر Keenpix وPostgres داخل Docker مع volumes دائمة وطبقة CDN أمام الصور

تشغيل CDN للصور باستخدام Docker: قائمة فحص للإنتاج

نشر Keenpix بصورة Docker مثبتة الإصدار، مع Postgres دائم، وفحص health، وقواعد كاش صحيحة، ونسخة احتياطية قبل الترقية، وتحقق بعد النشر.

self-hostingdockeroperations

نجاح docker compose up -d لا يعني أن خدمة الصور جاهزة للإنتاج. قد تظهر الحاويات السبع بحالة healthy، لكن قاعدة البيانات بلا نسخة احتياطية، وقد تنحرف وسوم الصور الأربع عند السحب التالي. وقد يخزّن الـ proxy صفحة تسجيل الدخول إن كانت قاعدة الكاش واسعة أكثر من اللازم.

تشغيل الحاوية هو الفحص الأول فقط. ما يأتي بعده هو ما يحدد إن كان النشر قابلاً للصيانة.

ما الذي يعمل داخل Compose؟

يشغّل ملف docker-compose.yml سبع خدمات: PostgreSQL 18 وDragonfly وMaxIO، إضافة إلى التطبيق وخدمة التحويل والـ worker وموقع التوثيق. للخدمات الأساسية readiness checks، وينتظر التطبيق جاهزية الاعتماديات قبل أن يبدأ.

يملك Postgres volume مستقلاً، ويملك كاش الصور volume آخر. الفرق مهم: قاعدة البيانات تحتوي المشاريع والمستخدمين والإعدادات، لذلك تحتاج إلى backup. أما كاش الصور فيمكن إعادة بنائه من المصادر، ولا يجوز اعتباره نسخة من ملفاتك الأصلية.

عند البدء يشغّل entrypoint ترحيلات Prisma والـ seed الأولي، ثم يعمل التطبيق تحت مستخدم node غير ذي صلاحيات إدارية ويعرض /api/health على المنفذ 3000.

ثبّت الإصدار ولا تعتمد على latest

الإعداد الافتراضي يسحب latest. هذا مناسب لتجربة سريعة، لكنه يجعل الترقية غير واضحة. ابدأ من release محدد:

git clone --branch v0.3.0 --depth 1 https://github.com/lord007tn/keenpix.git
cd keenpix
cp .env.example .env

ضع القيم الأساسية في .env:

KEENPIX_APP_IMAGE=ghcr.io/lord007tn/keenpix-app:v0.3.0
KEENPIX_TRANSFORM_IMAGE=ghcr.io/lord007tn/keenpix-transform:v0.3.0
KEENPIX_WORKER_IMAGE=ghcr.io/lord007tn/keenpix-worker:v0.3.0
KEENPIX_DOCS_IMAGE=ghcr.io/lord007tn/keenpix-docs:v0.3.0
POSTGRES_PASSWORD=<a-long-random-password>
BETTER_AUTH_SECRET=<output-of-openssl-rand-hex-32>
BETTER_AUTH_URL=https://admin.images.example.com
KEENPIX_APP_URL=https://admin.images.example.com
KEENPIX_SUPER_ADMIN_EMAIL=admin@example.com
KEENPIX_SUPER_ADMIN_PASSWORD=<a-different-long-password>

أنشئ قيمة BETTER_AUTH_SECRET فعلياً:

openssl rand -hex 32

ثم اسحب الصورة وشغّلها:

docker compose pull
docker compose up -d
docker compose ps

لا تفتح منفذ Postgres للعامة. ملف Compose الموجود في المشروع يبقيه داخل الشبكة، ويعرض منفذ التطبيق فقط.

افصل لوحة التحكم عن كاش الصور

ضع HTTPS أمام التطبيق باستخدام Caddy أو Nginx أو proxy الخاص بـ Coolify أو CDN. يجب أن تشير BETTER_AUTH_URL وKEENPIX_APP_URL إلى عنوان لوحة التحكم العام نفسه، حتى لا تختلف روابط auth والكوكيز عن العنوان الذي يفتحه المستخدم.

قاعدة الكاش تخص /img/* فقط. لا تخزّن /app أو /api/auth أو /api/health. قاعدة cache everything على الدومين كله قد تحتفظ باستجابة مرتبطة بجلسة مستخدم.

يجب أن يدخل المسار الكامل والـ query string في cache key. هذان رابطان لنسختين مختلفتين:

/img/https://assets.example.com/hero.jpg?project=store&w=640&fmt=webp
/img/https://assets.example.com/hero.jpg?project=store&w=1200&fmt=webp

وإذا استخدمت fmt=auto، فيجب أن يفصل الكاش النتائج حسب Accept. عندما لا تستطيع إثبات ذلك، ضع fmt=avif أو fmt=webp أو fmt=jpeg في الرابط.

اختبار حقيقي بعد إنشاء المشروع

ادخل بحساب super admin، وأنشئ مشروعاً، ثم أضف نطاق المصدر إلى allowed hosts. بعد ذلك اطلب صورة تعرفها:

curl -sS -D transform.headers -o transformed.webp \
  'https://images.example.com/img/https://assets.example.com/catalog/chair.jpg?project=PROJECT_ID&w=1200&fmt=webp&q=80'

لا تكتفِ برقم 200. تحقق من الآتي:

  • Content-Type يساوي image/webp؛
  • Cache-Control يسمح بتخزين التحويل؛
  • أبعاد الملف توافق الطلب وحدود المصدر؛
  • نطاق غير موجود في allowlist يُرفض؛
  • الطلب الثاني يتحول إلى HIT في طبقة الكاش التي تقصد اختبارها.

راجع health والـ logs أيضاً:

curl -fsS https://admin.images.example.com/api/health
docker compose logs --since=10m app

نجاح healthcheck يثبت أن هذه النسخة أجابت عن فحوصها الحالية. لا يختبر كل origin أو تحويل أو منطقة CDN.

النسخة الاحتياطية تسبق أول ترقية

أنشئ backup قبل أن يضيف الفريق المشاريع والدعوات، ثم جرّب استعادته في بيئة منفصلة. كبداية، تستطيع إخراج dump من خدمة Postgres الموجودة:

docker compose exec -T postgres sh -lc \
  'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' \
  > keenpix-$(date +%F).dump

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

قبل الترقية، اقرأ release notes، وخذ dump جديداً، ثم غيّر متغيرات KEENPIX_*_IMAGE الأربعة إلى الإصدار المطلوب:

docker compose pull app transform worker docs
docker compose up -d app transform worker docs
docker compose ps

يشغّل entrypoint ترحيلات قاعدة البيانات. احتفظ بمرجع الصورة السابقة وخطوات restore مجرّبة إلى أن ينجح smoke test.

راقب الحدود التي اخترتها

الحد الافتراضي لكاش القرص في Compose هو 8 GB. اضبط KEENPIX_CACHE_MAX_BYTES حسب مساحة القرص، ثم راقب عمليات eviction. لا يوفّر مسار تحويل HTTP حالياً إعداداً عاماً لعدد التحويلات المتزامنة؛ أضف حد قبول مضبوطاً في الوكيل أو منصة التشغيل كي ترفض الحمل البارد الزائد قبل استنزاف ذاكرة الخادم.

عند تشغيل أكثر من replica، لا تشترك الحاويات في كاش القرص المحلي. يستخدم الإعداد المرفق MaxIO لطبقة object storage مشتركة، ويمكن استبداله بـ R2 أو خدمة متوافقة مع S3. ضع CDN أمام خدمة التحويل. أما Postgres فيحتاج إلى خطة منفصلة للتوافر والنسخ الاحتياطي إذا كانت الخدمة جزءاً من مسار إنتاج فعلي.

متى أختار الخدمة المدارة؟

الاستضافة الذاتية تلغي فاتورة الخدمة المدارة، لكنها تنقل إليك التحديثات والمراقبة والنسخ الاحتياطي ومنع الإساءة والاستجابة للأعطال. اخترها عندما تبرر السيطرة على البنية أو مكان البيانات أو تعديل كود AGPL-3.0 هذا العمل.

إذا كان الفريق يريد تسليم الصور ولا يريد تشغيل هذا المسار، فالخدمة المدارة أبسط. قواعد روابط التحويل متشابهة، لكن مسؤولية التشغيل مختلفة تماماً.

المراجع

حُدّث هذا الدليل في 18 أغسطس 2026 من أجل إصدار Keenpix v0.3.0، وملفات Docker الأربعة وdocker-compose.yml في المشروع، وإعدادات النشر، ومرجع configuration، وإعداد CDN. هذه قائمة فحص للنشر، وليست وعداً بأن كل بيئة تُجهّز في مدة ثابتة.

صور محسّنة وفاتورة يمكن فهمها.

استخدم الخدمة المدارة أو شغّل المحرك مفتوح المصدر على خادمك.