الحاويات وDocker — دليل مصوّر

لا بد أنك سمعت أحدهم يقول: «يعمل على جهازي». والحاويات تحل هذه المشكلة.

المشكلة

بدون الحاويات، يحتاج كل مطوّر إلى:

  • تثبيت نسخة Python نفسها بالضبط
  • تثبيت مكتبات النظام نفسها بالضبط
  • ضبط نظام التشغيل لديك على النحو الصحيح تمامًا
  • الأمل في ألا يتعارض شيء مع مشاريع أخرى

واختلاف واحد في البيئة يعني: «يعمل على جهازي، لكنه لا يعمل على جهازك».

ما هي الحاوية؟

تخيّل حاوية شحن:

  • تحمل حاوية الشحن بضائع من أي نوع
  • وتعمل بالطريقة نفسها على السفينة أو الشاحنة أو القطار
  • ولا يهمك ما بداخلها — فكل ما تفعله هو نقل الحاوية

وحاوية البرمجيات تقوم على الفكرة نفسها:

  • تحتوي على تطبيقك + كل تبعياته (Python، والمكتبات، والإعدادات)
  • وتعمل بالطريقة نفسها على حاسوبك المحمول، أو حاسوب زميلك، أو خادم سحابي
  • ولست بحاجة إلى تثبيت Python — فهو موجود داخل الحاوية

الحاوية مقابل الآلة الافتراضية

┌─────────────────────────┐    ┌─────────────────────────┐
│  App A  │  App B        │    │  App A     │  App B     │
│  Libs    │  Libs         │    │  Libs       │  Libs      │
│  Guest OS│  Guest OS     │    │  ──── shared ────       │
│  ──── Hypervisor ────   │    │  Host OS                  │
│  Host OS                  │    │  Hardware                 │
│  Hardware                 │    └─────────────────────────┘
└─────────────────────────┘    Container (Docker)
   Virtual Machine
الآلة الافتراضية الحاوية
نظام التشغيل لكل آلة افتراضية نظام تشغيل خاص بها يتشارك نظام تشغيل المضيف
زمن البدء دقائق ثوانٍ
الحجم غيغابايت ميغابايت
العزل كامل على مستوى العملية

Docker

Docker هي منصة الحاويات الأكثر استخدامًا، وتقوم على ثلاثة مفاهيم أساسية:

1. Dockerfile — الوصفة

يشبه ملف Dockerfile وصفة لخبز كعكة: فهو يسرد كل مكوّن وكل خطوة:

FROM python:3.13-slim    # ابدأ من هذه الصورة الأساسية (مثل «ابدأ بالطحين»)
WORKDIR /app              # حدّد مجلد العمل
COPY app/requirements.txt .  # أضف قائمة المكوّنات
RUN pip install -r requirements.txt  # ثبّت المكوّنات
COPY app/ ./app/          # أضف كودك
EXPOSE 5000               # افتح الباب (المنفذ)
CMD ["python", "app/__init__.py"]  # شغّل التطبيق

2. الصورة — الكعكة المخبوزة

الصورة هي ما تحصل عليه بعد بناء ملف Dockerfile. وهي حزمة مجمّدة جاهزة للتشغيل، يمكنك مشاركتها وتخزينها وتشغيلها في أي مكان.

3. الحاوية — الكعكة التي تُؤكل

الحاوية هي نسخة قيد التشغيل من صورة ما. ويمكنك تشغيل عدة حاويات من الصورة نفسها (تمامًا كما يمكن لعدة أشخاص أن يأكلوا شرائح من الكعكة نفسها).

تدفّق البناء → التشغيل

docker build -t my-app .   # اخبز الكعكة (ابنِ الصورة)
docker run my-app           # كُل الكعكة (شغّل الحاوية)

Docker Compose — حاويات متعددة

تحتاج التطبيقات الحقيقية إلى أكثر من خدمة واحدة: خادم ويب + قاعدة بيانات + ربما ذاكرة تخزين مؤقت (cache). ويتيح لك Docker Compose تعريفها كلها في ملف واحد:

services:
  app:
    build: .              # ابنِ الصورة من Dockerfile
    ports:
      - "5000:5000"       # اربط المنفذ 5000 من الداخل → الخارج
    volumes:
      - .:/app            # إعادة تحميل الكود مباشرة
    env_file:
      - app/.env          # حمّل المتغيرات السرية

شغّل كل شيء بأمر واحد:

docker compose up

أوقف كل شيء:

docker compose down

كيف تُستخدم Docker في هذا المشروع

البيئة الملف الغرض
التطوير backend/Dockerfile يشغّل Flask في وضع التصحيح، مع إعادة تحميل مباشرة عبر ربط وحدة تخزين، وSQLite
التطوير backend/docker-compose.yml خدمة واحدة: تطبيق Flask مع ربط المنافذ + ملف .env
الإنتاج backend/Dockerfile.prod يشغّل Flask مع Gunicorn (خادم الإنتاج)، دون وضع التصحيح
RAG advanced/docker-compose.rag.yml يضيف PostgreSQL + pgvector إلى جانب تطبيق Flask

أوامر Docker الأساسية

الأمر ما الذي يفعله متى تستخدمه
docker compose build بناء الصور أو إعادة بنائها بعد تغيير Dockerfile أو requirements
docker compose up تشغيل كل الخدمات عندما تريد تشغيل التطبيق
docker compose down إيقاف كل الخدمات عندما تنتهي
docker compose down -v الإيقاف + حذف وحدات التخزين لإعادة ضبط قاعدة البيانات
docker compose logs عرض سجلات الخدمات لتصحيح الأخطاء
docker compose exec app bash فتح صدفة (shell) داخل الحاوية لفحص البيئة
docker compose run app python -c "..." تشغيل أمر واحد داخل الحاوية لاختبارات سريعة

وحدات التخزين — حفظ البيانات

الحاويات مؤقتة: عند إيقاف الحاوية تختفي كل ملفاتها. أما وحدات التخزين فتحفظ البيانات خارج الحاوية:

volumes:
  - .:/app               # اربط كودك بالحاوية (إعادة تحميل مباشرة)
  - sqlite_data:/app/instance  # احفظ قاعدة بيانات SQLite

volumes:
  sqlite_data:           # وحدة تخزين مسماة (تبقى بعد إعادة التشغيل)
  • ربط مجلد (bind mount) (. :/app) — يربط مجلدًا على حاسوبك بمجلد داخل الحاوية، فتظهر التغييرات التي تُجريها في أحدهما في الآخر.
  • وحدة تخزين مسماة (named volume) (sqlite_data:/app/instance) — يتولى Docker إدارة التخزين، وتبقى بعد docker compose down، لكنها تختفي بعد docker compose down -v.

Docker في الإنتاج (Hugging Face Spaces)

عند النشر على Hugging Face Spaces، تعمل صورة Docker نفسها في السحابة:

حاسوبك المحمول:  docker compose up  → يشغّل حاوية بكودك
Hugging Face:    يقرأ Dockerfile.prod → يبني → يشغّل حاوية على hf.space

الصورة نفسها، والسلوك نفسه، لكن المكان مختلف.

ملخص مصوّر

┌───────────────────────────────────────────────────────┐
│                   Docker Architecture                  │
│                                                       │
│  ┌──────────┐    ┌──────────┐    ┌──────────┐        │
│  │ Docker    │    │ Docker   │    │ Container│        │
│  │ Client    │───▶│ Daemon   │───▶│ (running │        │
│  │ (docker   │    │ (engine) │    │  image)  │        │
│  │  command) │    │          │    └──────────┘        │
│  └──────────┘    │          │    ┌──────────┐        │
│                  │          │    │ Image    │        │
│                  │          │◀───│ (stored  │        │
│                  │          │    │  recipe) │        │
│                  └──────────┘    └──────────┘        │
│                                                       │
│  ┌──────────────┐    ┌─────────────────────────┐      │
│  │ Dockerfile   │───▶│ Image (immutable snapshot)│    │
│  │ (recipe)     │    │ with Python + deps + code│     │
│  └──────────────┘    └──────────┬──────────────┘      │
│                                 ▼                     │
│                          ┌──────────────┐             │
│                          │ Container    │             │
│                          │ (running app)│             │
│                          └──────────────┘             │
└───────────────────────────────────────────────────────┘