
BackendDevOpsDocker
Docker: شغّل مشروعك كاملاً بتعليمة وحدة، وعلى أي جهاز
هل سمعت يوماً جملة «بس على جهازي يشتغل!»؟ هي أشهر جملة في عالم البرمجة، وغالباً تعني أن المشروع يعمل عند مبرمج ويتعطّل عند آخر، لأن نسخة Python مختلفة، أو قاعدة البيانات غير مثبّتة، أو إعداداً صغيراً منسيّاً.
خادم SYREUS ليس برنامجاً واحداً. خلف كل صفحة تفتحها في المنصة ست خدمات تعمل معاً:
web: تطبيق Django الذي يجيب على طلبات الموقع والتطبيق.
db: قاعدة بيانات PostgreSQL، وفيها حسابك وتقدّمك ونقاطك.
redis: ذاكرة سريعة تمرّر المهام بين الخدمات.
worker: عامل Celery ينفّذ المهام الثقيلة في الخلفية، مثل إرسال هذه المقالة إلى المشتركين في النشرة البريدية.
beat: منبّه يشغّل المهام المجدولة، مثل تذكير الفعاليات كل خمس دقائق وإغلاق يوم السلسلة عند منتصف الليل.
caddy: البوّابة التي تستقبل الزوّار وتفعّل HTTPS تلقائياً.
تخيّل أن تثبّت هذا كله يدوياً، بالنسخ الصحيحة، على جهازك وجهاز زميلك والسيرفر. هنا يأتي دور Docker.
ما هو Docker؟
فكّر في حاويات الشحن. السفينة لا يهمّها ما في الحاوية، أثاثاً كان أو فواكه أو سيارات، فكل الحاويات بالشكل والمقاس نفسه وتُنقل بالطريقة نفسها. Docker يفعل الشيء ذاته مع البرامج: يضع برنامجك مع كل ما يحتاجه (نسخة اللغة والمكتبات والإعدادات) في حاوية واحدة تعمل بالطريقة نفسها على أي جهاز فيه Docker.
ستسمع كلمتين كثيراً:
الصورة (Image): الوصفة الجاهزة لبرنامجك، تُبنى مرة واحدة ولا تتغيّر.
الحاوية (Container): نسخة تعمل من تلك الصورة. يمكنك تشغيل عدة حاويات من صورة واحدة، كما تطبخ عدة أطباق من وصفة واحدة.
وهذا ما نفعله فعلاً: web وworker وbeat ثلاث حاويات من الصورة نفسها، كل واحدة منها تشغّل أمراً مختلفاً.
Dockerfile: وصفة الصورة
تُبنى الصورة من ملف نصي اسمه Dockerfile. هذه نسخة مختصرة من ملفنا:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt ./
RUN pip install -r requirements.txt
COPY . .
CMD ["gunicorn", "config.wsgi:application", "--bind", "0.0.0.0:8000"]
اقرأها كأنها خطوات طبخ: ابدأ من نظام فيه Python 3.12، وادخل مجلد /app، وانسخ قائمة المكتبات وثبّتها، ثم انسخ الكود وشغّل الخادم.
لاحظ أننا ننسخ requirements.txt وحده قبل باقي الكود. Docker يحفظ نتيجة كل خطوة، فإذا عدّلت سطراً في الكود ولم تتغيّر المكتبات، لا يعيد تثبيتها ويصبح البناء أسرع بكثير.
Docker Compose: الفرقة كاملة
الـ Dockerfile يصف خدمة واحدة، أما ملف docker-compose.yml فيصف الفرقة كلها: أي الخدمات تعمل، وكيف تتصل ببعضها، ومن ينتظر من. هذا مقطع منه:
services:
db:
image: postgres:17-alpine
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready"]
web:
build: ./backend
environment:
POSTGRES_HOST: db
depends_on:
db:
condition: service_healthy
شيئان يستحقان الانتباه هنا. الأول أن web يصل إلى قاعدة البيانات بالاسم db لا بعنوان IP، لأن Compose يضع الخدمات في شبكة واحدة يعرف فيها كل منها الآخر باسمه. والثاني أن web لا يبدأ قبل أن يؤكّد فحص الصحة (healthcheck) أن قاعدة البيانات جاهزة فعلاً، فلا يتعطّل لأنه سبقها.
أمر واحد
docker compose up -d
بهذا الأمر يحمّل Docker صور PostgreSQL وRedis وCaddy، ويبني صورة Django من الـ Dockerfile، وينتظر قاعدة البيانات، ثم يحدّث جداولها (migrations) ويشغّل الخدمات الست. نستخدم الأمر نفسه على أجهزتنا وعلى السيرفر، فلا توجد خطوات «للسيرفر فقط» قد ينساها أحد.
وأين تذهب البيانات؟
الحاويات مؤقتة، يمكنك حذفها وإعادة بنائها متى شئت. لذلك لا نترك البيانات داخلها، بل في مخزن منفصل اسمه volume، مثل pgdata في المثال. تُحذف حاوية قاعدة البيانات وتُبنى من جديد، ويبقى حسابك ونقاطك في مكانهم.
انتبه: الأمر docker compose down يوقف الخدمات ويحتفظ بالبيانات، أما docker compose down -v فيحذف الـ volumes معها. لا تكتبه على سيرفر حقيقي.
ما الذي كسبناه؟
بيئة واحدة للجميع: النسخ نفسها على كل جهاز، فلا مفاجآت.
بداية سريعة: عضو جديد في الفريق يشغّل الخادم كاملاً في دقائق، لا في يوم كامل.
نشر بسيط: يكفي أي سيرفر Linux فيه Docker.
عزل: نسخة PostgreSQL الخاصة بنا لا تتعارض مع نسخة يستخدمها مشروع آخر على الجهاز نفسه.
تعافٍ تلقائي: مع restart: unless-stopped تعود أي خدمة متوقفة إلى العمل من تلقاء نفسها، حتى بعد إعادة تشغيل السيرفر.
جرّبه بنفسك
ثبّت Docker Desktop، ثم اكتب في سطر الأوامر:
docker run --rm -p 8080:80 nginx
افتح http://localhost:8080 في المتصفح: خادم ويب كامل يعمل على جهازك، ولم تثبّت شيئاً سوى Docker نفسه. أوقفه بـ Ctrl+C فتُحذف الحاوية تلقائياً.
وفي المرة القادمة التي يقول لك فيها أحد «على جهازي يشتغل»، أجبه: «ممتاز، سنشحن جهازك إذن». هذه النكتة القديمة هي بالضبط فكرة Docker.
لا تعليقات