وداعًا لدليل التثبيت ذي الـ 30 خطوة: كيف أنقذنا Docker Compose من جحيم إعداد المشاريع؟

يا جماعة الخير، السلام عليكم ورحمة الله وبركاته. معكم أخوكم أبو عمر.

بتذكر قبل كم سنة، انضم لفريقنا شب جديد، خلينا نسميه “خالد”. خالد مبرمج شاطر وعين الله عليه، متحمس يبدأ يشتغل ويفرجينا إبداعه. أعطيناه الوصول للكود تبع المشروع الجديد، مشروع ضخم فيه خدمات مصغرة (microservices)، وقواعد بيانات من نوعين، ونظام كاش (caching)، وقصص طويلة عريضة.

قلتله: “يا خالد، هي الـ README، اقرأها وامشي مع الخطوات، ولو احتجت إشي أنا موجود”. ابتسم الشب ابتسامة الواثق، وأنا ابتسمت ابتسامة اللي عارف شو اللي جاي. بعد ساعتين، إجا خالد مكتبي، وجهه مقلوب، وقال لي الجملة اللي كل مدير فريق بكرهها: “يا أبو عمر، مش زابط معي… إشي بطلعلي error غريب!”.

قعدنا أنا وهو يومين كاملين! نعم، يومين ونحن بنحاول نثبّت نسخة PHP معينة، مع امتدادات (extensions) خاصة، ونسخة PostgreSQL محددة، و Redis، وكل واحد فيهم بده إعدادات معينة وملفات config لازم تتعدل. والمشكلة الكبرى كانت جملة “It works on my machine” أو “والله شغّال عندي!”، كل واحد فينا عنده إعدادات مختلفة شوي على جهازه، واللي بيشتغل عندي ما بيشتغل عنده.

في نهاية اليوم الثاني، وبعد ما انحلت المشكلة أخيرًا، جمعت الفريق وقلتلهم: “يا جماعة، هاد الحكي مش منطق. إحنا بنضيّع وقتنا وجهدنا في إعداد البيئة بدل ما نكتب كود ونحل مشاكل حقيقية. لازم نلاقي حل”. ومن هنا بدأت رحلتنا مع Docker، وتحديدًا Docker Compose، اللي أنقذنا من هذا الكابوس.

ما هو Docker أصلًا؟ (ولماذا لم يكن كافيًا لوحده؟)

قبل ما نحكي عن المنقذ Docker Compose، لازم نفهم الأداة الأساسية: Docker. ببساطة شديدة، تخيل إنك بتقدر تحط تطبيقك وكل إشي بيحتاجه عشان يشتغل (المكتبات، الإعدادات، وحتى نظام التشغيل المصغّر) داخل “صندوق” أو “حاوية” (Container). هذا الصندوق معزول تمامًا عن جهازك الأصلي، وتقدر تشغّله على أي جهاز ثاني عليه Docker بدون أي مشاكل.

هذا الحل العبقري قضى على مشكلة “شغّال عندي!”. صار النقاش: “هل هو شغال جوا الحاوية؟”. إذا الجواب نعم، فالمشكلة انحلت.

لكن، واجهتنا مشكلة جديدة. مشروعنا ما كان تطبيق واحد، كان عبارة عن:

  • خدمة خلفية (Backend API) مكتوبة بلغة Node.js.
  • واجهة أمامية (Frontend) مكتوبة بـ React.
  • قاعدة بيانات PostgreSQL.
  • خدمة كاش باستخدام Redis.

صرنا محتاجين نشغّل 4 حاويات مختلفة، ونخليهم يتواصلوا مع بعض. كنا بنكتب أوامر طويلة ومعقدة في الـ terminal لكل حاوية، مثل docker run --name my-db -e POSTGRES_PASSWORD=... -v ... -p ... postgres. كان الموضوع متعب وعرضة للأخطاء، وفقدنا الفائدة الأساسية: البساطة.

وهنا يأتي المنقذ: Docker Compose

Docker Compose هو الأداة اللي بتخليك تدير التطبيقات متعددة الحاويات بسهولة. هو مثل “المُنسّق” أو “المايسترو” اللي بيقرأ ملف واحد، وبيفهم منه كل الخدمات اللي مشروعك بيحتاجها، وكيف لازم تشتغل مع بعضها.

القصة وما فيها، إنك بتكتب كل إعدادات خدماتك (الـ API، قاعدة البيانات، إلخ) في ملف واحد بصيغة YAML اسمه docker-compose.yml. بعدين، وبأمر واحد بسيط جدًا، بتخلّي Docker Compose يشغّل كل هاي الخدمات ويوصلها ببعضها.

ببساطة: Docker هو “الحاوية”، و Docker Compose هو “مدير الحاويات” اللي بينظمها وبيخليها تشتغل مع بعض بانسجام.

لنطبق عمليًا: بناء بيئة تطوير لمشروع ويب بسيط

خلينا نأخذ مثال عملي عشان الصورة توضح. تخيل عنا تطبيق ويب بسيط مكون من خدمة خلفية بـ Node.js وقاعدة بيانات PostgreSQL.

السيناريو: تطبيق ويب بـ Node.js مع قاعدة بيانات PostgreSQL

المشروع يتكون من:

  1. خدمة `api`: تطبيق Express.js بسيط يتصل بقاعدة البيانات.
  2. خدمة `db`: قاعدة بيانات PostgreSQL لتخزين البيانات.

قبل Docker Compose: الكابوس

لإعداد هذا المشروع يدويًا، كنت ستحتاج إلى:

  • تثبيت Node.js (والتأكد من أنها النسخة الصحيحة).
  • تثبيت PostgreSQL على جهازك.
  • إنشاء قاعدة بيانات ومستخدم خاص بالتطبيق.
  • تذكر اسم المستخدم وكلمة المرور وتحديثها في ملف .env.
  • تشغيل PostgreSQL في الخلفية.
  • تشغيل تطبيق Node.js في الـ terminal.
  • وكل هذا قبل كتابة سطر كود واحد!

مع Docker Compose: السحر

الآن، انسَ كل ما سبق. كل ما نحتاجه هو ملفين: Dockerfile لتطبيقنا، و docker-compose.yml لتنسيق كل شيء.

1. ملف `Dockerfile` لخدمة الـ API (ضعه في مجلد الـ API):

# استخدم صورة Node.js رسمية
FROM node:18

# أنشئ مجلد العمل داخل الحاوية
WORKDIR /usr/src/app

# انسخ ملفات package.json و package-lock.json
COPY package*.json ./

# ثبّت الاعتماديات
RUN npm install

# انسخ باقي ملفات المشروع
COPY . .

# عرّض البورت الذي يعمل عليه التطبيق
EXPOSE 3000

# الأمر الافتراضي لتشغيل التطبيق
CMD [ "node", "server.js" ]

2. ملف docker-compose.yml (ضعه في جذر المشروع):

version: '3.8'

services:
  # خدمة قاعدة البيانات
  db:
    image: postgres:14-alpine  # استخدم صورة رسمية وخفيفة
    restart: always
    environment:
      - POSTGRES_USER=abu_omar
      - POSTGRES_PASSWORD=supersecretpassword
      - POSTGRES_DB=my_app_db
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432" # اختياري: لتمكين الوصول من خارج Docker

  # خدمة الـ API
  api:
    build: . # ابني الصورة من الـ Dockerfile في نفس المجلد
    restart: always
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgres://abu_omar:supersecretpassword@db:5432/my_app_db
    depends_on:
      - db # لا تشغل الـ API إلا بعد أن تبدأ قاعدة البيانات
    volumes:
      - .:/usr/src/app # مهم جدًا للتطوير: مزامنة الكود مباشرة

volumes:
  postgres_data: # هذا يضمن عدم فقدان بياناتك عند إيقاف الحاويات

الآن، كل ما على المبرمج الجديد “خالد” فعله هو:

  1. تثبيت Docker و Docker Compose على جهازه.
  2. تحميل الكود من Git.
  3. فتح الـ terminal وكتابة أمر واحد: docker-compose up.

وهذا كل شيء! خلال دقائق، سيتم بناء حاوية الـ API، وتشغيل حاوية قاعدة البيانات، وتوصيلهما معًا، وسيصبح المشروع جاهزًا للتطوير. لا مزيد من أدلة التثبيت الطويلة، ولا مزيد من “مش زابط معي!”.

نصائح من خبرة أبو عمر (شغلات ما بتلاقيها بالـ Docs)

على مدار السنين، تعلمت كم شغلة مهمة في التعامل مع Docker Compose، بحب أشاركها معكم:

  • لا تعيد اختراع العجلة: استخدم دائمًا الصور الرسمية (Official Images) من Docker Hub قدر الإمكان (مثل `postgres`, `node`, `redis`). فهي مُحسّنة وآمنة وموثوقة.
  • حافظ على بياناتك يا غالي: لاحظت في المثال كيف استخدمنا `volumes` مع `postgres_data`؟ هذا يُسمى “Named Volume”. هذا يضمن أن بيانات قاعدة بياناتك ستبقى محفوظة حتى لو حذفت الحاويات وأعدت بناءها. لا تخزن بيانات قاعدة البيانات داخل الحاوية مباشرة أبدًا!
  • استخدم `depends_on` بحكمة: `depends_on` تضمن ترتيب بدء تشغيل الحاويات، لكنها لا تضمن أن الخدمة داخل الحاوية (مثل قاعدة البيانات) أصبحت جاهزة لاستقبال الاتصالات. في المشاريع المعقدة، قد تحتاج إلى استخدام سكربتات “wait-for-it” للتأكد من جاهزية الخدمات قبل المتابعة.
  • افصل بين بيئة التطوير والإنتاج: يمكنك استخدام ملف `docker-compose.override.yml` لتعديل إعدادات التطوير. مثلًا، في التطوير، نستخدم `volumes` لمزامنة الكود مباشرة (live reload)، لكن في الإنتاج، ننسخ الكود داخل الصورة مرة واحدة عند البناء.
  • تعلم الأوامر الأساسية:
    • docker-compose up -d: لتشغيل كل شيء في الخلفية.
    • docker-compose down: لإيقاف وحذف الحاويات والشبكات.
    • docker-compose logs -f api: لمشاهدة سجلات (logs) خدمة معينة بشكل مباشر.
    • docker-compose exec api bash: للدخول إلى حاوية وتشغيل الأوامر بداخلها (مفيدة جدًا لتصحيح الأخطاء).

الخلاصة: استثمر في بيئتك، تربح وقتك وجهدك ✅

من الآخر، الانتقال إلى Docker Compose لم يكن مجرد تغيير تقني، بل كان تغييرًا في عقلية الفريق بأكمله. وفرنا مئات الساعات التي كانت تضيع في الإعدادات وحل مشاكل التوافق، ووجهنا هذا الوقت والجهد نحو ما يهم حقًا: بناء منتج رائع لعملائنا.

نصيحتي لك: لا تنظر إلى Docker Compose على أنه مجرد “أداة DevOps”. هو أداة أساسية لكل مطور. استثمار يوم أو يومين في تعلم أساسياته سيوفر عليك وعلى فريقك أسابيع من الصداع والإحباط على المدى الطويل. ابدأ اليوم، ولو بمشروع شخصي صغير، وستشكرني لاحقًا. 🚀

والله ولي التوفيق.

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

​معمارية البرمجيات

كان كودنا لا يفهم طبيعة عملنا: كيف أنقذنا ‘التصميم الموجه بالمجال’ (DDD) من جحيم ‘ماذا تفعل هذه الدالة؟’

كودنا كان يتحدث لغة لا يفهمها خبراء العمل، مما خلق فوضى عارمة. في هذه المقالة، أشارككم قصة كيف ساعدنا التصميم الموجه بالمجال (DDD) في بناء...

26 مايو، 2026 قراءة المزيد
خوارزميات

كانت دوالنا تعاني من فقدان الذاكرة: كيف أنقذتنا ‘البرمجة الديناميكية’ من جحيم إعادة الحسابات المتكررة؟

في هذه المقالة، يشاركنا أبو عمر، مبرمج فلسطيني خبير، قصة من أرض الواقع عن كيفية ترويض الخوارزميات البطيئة. استكشف معنا مفهوم البرمجة الديناميكية، وتعلم كيف...

26 مايو، 2026 قراءة المزيد
تجربة المستخدم والابداع البصري

كان تطبيقنا جميلاً ولكن أعمى: كيف أنقذتنا ‘إمكانية الوصول’ من جحيم استبعاد 15% من المستخدمين؟

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

26 مايو، 2026 قراءة المزيد
الشبكات والـ APIs

كانت تطبيقاتنا تعتمد على التحديث اليدوي: كيف أنقذتنا WebSockets من جحيم ‘الاستقصاء المستمر’ (Polling)؟

مقالة تستعرض تجربة عملية في الانتقال من تقنية الاستقصاء المستمر (Polling) المرهقة إلى استخدام WebSockets لتطبيقات الوقت الحقيقي. اكتشف كيف يمكن لهذا التغيير أن يحسّن...

26 مايو، 2026 قراءة المزيد
البودكاست