Docker للمطورين: الصور والحاويات وCompose

DevOps2026-10-12TryQuickToolBox

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

يشرح هذا الدليل الأفكار الثلاث التي تحتاجها فعلاً: الصور، والحاويات، وCompose. ويبقى عمليًا، بأوامر يمكنك تشغيلها أثناء القراءة.

الصور مقابل الحاويات: النموذج الذهني

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

إذا كنت قادمًا من البرمجة كائنية التوجه، فالتشبيه قريب: الصورة هي الصنف، والحاوية هي الكائن. يمكنك تشغيل العديد من الحاويات من صورة واحدة، والتغييرات داخل الحاوية لا تعدّل الصورة.

المفهومما هوالأمر المعتاد
الصورةقالب غير قابل للتغييرdocker build, docker pull
الحاويةنسخة قيد التشغيلdocker run, docker ps
وحدة التخزينتخزين دائمdocker volume create
Composeتعريف متعدد الحاوياتdocker compose up

صورتك الأولى باستخدام Dockerfile

Dockerfile هو وصفة. كل تعليمة تُنشئ طبقة، ويخزّن Docker الطبقات مؤقتًا بحيث تكون عمليات إعادة البناء سريعة عندما لا يتغير شيء. إليك مثال صغير بـ Node.js:

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

هناك عادتان مهمتان هنا. أولاً، انسخ ملفات تعريف التبعيات قبل بقية الشيفرة المصدرية حتى تُخزَّن طبقة npm ci مؤقتًا عندما تتغير شيفرة التطبيق فقط. ثانيًا، فضّل صورة أساسية نحيفة مثل alpine لتقليل الحجم وسطح الهجوم.

ابنِها وشغّلها:

docker build -t myapp:1.0 .
docker run --rm -p 3000:3000 myapp:1.0

تُعيّن العلامة -p 3000:3000 منفذ المضيف 3000 إلى منفذ الحاوية 3000. و--rm يحذف الحاوية عند خروجها، مما يبقي جهازك مرتبًا أثناء التطوير.

أوامر الحاويات اليومية

تغطي هذه معظم العمل اليومي:

عندما تخرج الحاوية فورًا، اقرأ السجلات أولاً. الأسباب الأكثر شيوعًا هي CMD خاطئ، أو متغير بيئة مفقود، أو ربط العملية بـ 127.0.0.1 بدلاً من 0.0.0.0 داخل الحاوية.

لماذا وُجد Compose

عادةً ما يحتاج التطبيق الحقيقي إلى أكثر من عملية: واجهة برمجية، وقاعدة بيانات، وربما ذاكرة تخزين مؤقت. تشغيل ثلاثة أوامر docker run بقوائم علامات طويلة عرضة للخطأ. يتيح لك Docker Compose تعريف جميع الخدمات في ملف YAML واحد وتشغيلها معًا.

services:
  api:
    build: .
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgres://app:secret@db:5432/app
    depends_on:
      - db
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: app
    volumes:
      - db_data:/var/lib/postgresql/data
volumes:
  db_data:

لاحظ أن الواجهة البرمجية تتصل بـ db، وليس localhost. ينشئ Compose شبكة خاصة يمكن الوصول فيها إلى كل خدمة باسم خدمتها. وهذا هو المصدر الأكثر شيوعًا للارتباك لدى القادمين الجدد.

ابدأ كل شيء بالأمر docker compose up، أو docker compose up -d للتشغيل في الخلفية. أعد البناء بعد تغييرات الشيفرة بـ docker compose up --build. أوقف كل شيء بـ docker compose down، وأضف -v إذا كنت تريد أيضًا حذف وحدات التخزين المسماة.

وحدات التخزين والربط وإعادة التحميل المباشر

الحاويات مؤقتة؛ فالبيانات داخلها تختفي عند إزالتها. هناك آليتان تحلان هذا:

  1. وحدات التخزين المسماة — يديرها Docker، مثالية لملفات قواعد البيانات. تستمر عبر إعادة تشغيل الحاويات وتُعرَّف في قسم volumes:.
  2. عمليات الربط (Bind mounts) — تعيّن دليل المضيف داخل الحاوية، مثالية للشيفرة المصدرية أثناء التطوير.
services:
  api:
    build: .
    volumes:
      - ./src:/app/src

مع الربط، ينعكس تحرير الملفات على المضيف داخل الحاوية. اجمع هذا مع مراقب ملفات (nodemon، uvicorn --reload، air) وتحصل على إعادة تحميل مباشرة دون إعادة بناء الصورة.

سير عمل تطويري عملي

  1. اكتب Dockerfile لتطبيقك واجعله بسيطًا.
  2. أضف docker-compose.yml مع التطبيق وتبعياته.
  3. استخدم عمليات الربط للشيفرة المصدرية ووحدات التخزين المسماة للبيانات.
  4. أبقِ الأسرار خارج الملف؛ استخدم ملف .env وأشر إلى المتغيرات بـ ${VAR}.
  5. أضف .dockerignore يحتوي على node_modules و.git ومخرجات البناء لتسريع عمليات البناء.
  6. شغّل docker compose up --build وكرّر.

إذا كانت خدمتك تنتج سجلات تحتاج إلى فحصها لاحقًا، فتذكّر أن سجلات الحاويات مجرد نص. الأدوات التي تحلل سجلات الخادم، مثل محلل سجلات nginx، تتكامل جيدًا مع الحاويات لأنك تستطيع تمرير السجلات أو نسخها خارجيًا دون تثبيت أي شيء على المضيف.

مزالق شائعة

الأسئلة الشائعة

ما الفرق بين الصورة والحاوية؟

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

هل أحتاج Docker Compose لخدمة واحدة؟

لا. يكفي أمر docker run واحد لحاوية واحدة. يصبح Compose ذا قيمة عندما يكون لديك خدمات متعددة، أو شبكات مشتركة، أو متغيرات بيئة تريد تعريفها في مكان واحد.

كيف تتواصل الحاويات مع بعضها؟

يضع Compose جميع الخدمات على شبكة مشتركة يمكن الوصول فيها إلى كل خدمة باسم خدمتها. استخدم ذلك الاسم كاسم مضيف، مثلاً db:5432، بدلاً من localhost.

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