حاويات Docker
مقدمة
"يعمل على جهازي" هو عذر المطورين الكلاسيكي، وDocker يجعل هذا العذر يختفي تماماً. تقنية الحاويات تقوم بتغليف التطبيق وجميع تبعياته في وحدة موحدة، مما يضمن عمله بشكل متسق في أي بيئة. إنها حجر الأساس في تسليم البرمجيات الحديثة.
ماذا ستتعلم في هذا المقال؟
بعد إتمام هذا الفصل، ستحصل على:
- المفاهيم الأساسية: فهم المفاهيم الثلاثة الجوهرية: الصورة (Image)، الحاوية (Container)، المستودع (Registry)
- مقارنة البنى: فهم الفرق الجوهري بين الحاويات والآلات الافتراضية
- المهارات العملية: إتقان كتابة Dockerfile والأوامر الشائعة
- أساسيات التنسيق: تعلم إدارة التطبيقات متعددة الخدمات باستخدام Docker Compose
- أفضل الممارسات: التعرف على تحسين الصور وتعزيز الأمان والممارسات على مستوى الإنتاج
| الفصل | المحتوى | المفهوم الأساسي |
|---|---|---|
| الفصل 1 | لماذا نحتاج الحاويات | اتساق البيئة، كفاءة الموارد، التسليم الموحد |
| الفصل 2 | المفاهيم الأساسية | الصورة، الحاوية، المستودع، Dockerfile |
| الفصل 3 | دورة حياة Docker | كتابة، بناء، دفع، تشغيل، إدارة |
| الفصل 4 | Docker Compose | تنسيق متعدد الخدمات، الشبكات، مجلدات البيانات |
| الفصل 5 | أفضل الممارسات | تحسين الصور، الأمان، البناء متعدد المراحل |
1. لماذا نحتاج الحاويات؟
قبل ظهور الحاويات، كان نشر تطبيق يتطلب التثبيت اليدوي لبيئة التشغيل على الخادم، وتكوين متغيرات البيئة، ومعالجة تعارضات التبعيات. الاختلافات بين البيئات (التطوير، الاختبار، الإنتاج) كانت بيئة خصبة للأخطاء.
ما هي المشاكل التي تحلها الحاويات؟
| المشكلة | الطريقة التقليدية | طريقة الحاويات |
|---|---|---|
| عدم اتساق البيئة | "يعمل على جهازي" | تغليف جميع التبعيات، اتساق في كل مكان |
| تعارض التبعيات | التطبيق A يحتاج Node 14، التطبيق B يحتاج Node 18 | كل حاوية بيئة مستقلة |
| هدر الموارد | كل آلة افتراضية تحتاج نظام تشغيل كامل | مشاركة النواة، استهلاك بمستوى الميغابايت |
| النشر البطيء | تثبيت وتكوين يدوي | أمر واحد docker run |
| صعوبة التوسع | إنشاء آلة افتراضية جديدة، تثبيت البيئة، النشر | بدء حاويات جديدة في ثوانٍ |
جوهر الحاويات
الحاوية ليست آلة افتراضية خفيفة. جوهرها هو عملية معزولة. نواة Linux تنفذ الحاويات من خلال آليتين:
- Namespace: عزل رؤية العمليات (PID، الشبكة، نظام الملفات، إلخ)
- Cgroups: تقييد استخدام الموارد للعمليات (المعالج، الذاكرة، الإدخال/الإخراج)
العمليات داخل الحاوية لا تختلف جوهرياً عن العمليات العادية على المضيف، إنها فقط "محبوسة في غرفة لا تستطيع رؤية الخارج".
2. المفاهيم الأساسية
عالم Docker يدور حول ثلاثة مفاهيم جوهرية: الصورة (Image)، الحاوية (Container)، والمستودع (Registry).
| المفهوم | التشبيه | الوصف |
|---|---|---|
| الصورة (Image) | فئة / قالب | قالب للقراءة فقط يحتوي على الكود وبيئة التشغيل والمكتبات والتكوين |
| الحاوية (Container) | نسخة / كائن | نسخة تشغيل من الصورة، قابلة للقراءة والكتابة، لها دورة حياة مستقلة |
| المستودع (Registry) | متجر تطبيقات | خدمة تخزين وتوزيع الصور (Docker Hub، ACR، ECR) |
| Dockerfile | وصفة / مخطط | ملف نصي يحدد كيفية بناء الصورة |
| مجلد البيانات (Volume) | قرص صلب خارجي | استمرارية البيانات، لا تُفقد عند حذف الحاوية |
البنية الطبقية للصور
صور Docker تتكون من عدة طبقات للقراءة فقط (Layer)، كل تعليمة في Dockerfile تنشئ طبقة:
┌─────────────────────────┐
│ CMD ["node", "app.js"] │ ← طبقة أمر البدء
├─────────────────────────┤
│ COPY . /app │ ← طبقة كود التطبيق (تتغير كثيراً)
├─────────────────────────┤
│ RUN npm install │ ← طبقة تثبيت التبعيات (تتغير أحياناً)
├─────────────────────────┤
│ FROM node:18-alpine │ ← طبقة الصورة الأساسية (نادراً ما تتغير)
└─────────────────────────┘لماذا الطبقات مهمة؟
Docker يخزن كل طبقة مؤقتاً. إذا لم تتغير طبقة ما، يُعاد استخدام ذاكرة التخزين المؤقت أثناء البناء. لذلك في Dockerfile يجب وضع التعليمات الأقل تغييراً في البداية (مثل تثبيت التبعيات)، والأكثر تغييراً في النهاية (مثل نسخ الكود). هكذا معظم عمليات البناء ستستفيد من ذاكرة التخزين المؤقت وتكون أسرع بكثير.
3. دورة حياة Docker
من كتابة Dockerfile إلى تشغيل الحاوية، سير عمل Docker هو خط إنتاج واضح.
FROM node:18-alpineChoose the base imageWORKDIR /appSet the working directoryCOPY package*.json ./Copy dependency files for cache reuseRUN npm installInstall dependenciesCOPY . .Copy application codeEXPOSE 3000Declare the portCMD ["node", "server.js"]Start commandمرجع سريع لتعليمات Dockerfile
| التعليمة | الوظيفة | مثال |
|---|---|---|
FROM | تحديد الصورة الأساسية | FROM node:18-alpine |
WORKDIR | تعيين دليل العمل | WORKDIR /app |
COPY | نسخ ملفات إلى الصورة | COPY package.json ./ |
RUN | تنفيذ أوامر أثناء البناء | RUN npm install |
ENV | تعيين متغيرات البيئة | ENV NODE_ENV=production |
EXPOSE | تعريف منفذ (للتوثيق فقط) | EXPOSE 3000 |
CMD | أمر بدء الحاوية | CMD ["node", "app.js"] |
ENTRYPOINT | نقطة دخول الحاوية (صعب الكتابة فوقها) | ENTRYPOINT ["nginx"] |
4. Docker Compose: تنسيق متعدد الخدمات
المشاريع الحقيقية عادة تحتاج أكثر من حاوية واحدة. تطبيق ويب قد يحتاج: خادم تطبيقات + قاعدة بيانات + Redis + Nginx. Docker Compose يُعرّف ويدير حاويات متعددة بملف YAML واحد.
مثال docker-compose.yml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DB_HOST=db
- REDIS_HOST=redis
depends_on:
- db
- redis
db:
image: postgres:15-alpine
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=secret
redis:
image: redis:7-alpine
volumes:
db-data:المفاهيم الأساسية لـ Compose
| المفهوم | الوصف | مثال |
|---|---|---|
| services | تعريف خدمات الحاويات | app، db، redis |
| volumes | مجلدات البيانات المستمرة | db-data يحفظ ملفات قاعدة البيانات |
| networks | شبكة مخصصة (تُنشأ تلقائياً افتراضياً) | الخدمات تتواصل عبر اسم الخدمة |
| depends_on | تبعية ترتيب البدء | app يعتمد على db وredis |
| environment | متغيرات البيئة | كلمة مرور قاعدة البيانات، عنوان الاتصال |
اكتشاف الخدمات
في Docker Compose، اسم الخدمة هو اسم المضيف. حاوية app يمكنها الوصول مباشرة إلى قاعدة البيانات عبر db:5432 وإلى Redis عبر redis:6379، دون الحاجة لمعرفة عنوان IP. هذا بفضل DNS المدمج في Docker.
5. أفضل الممارسات
5.1 البناء متعدد المراحل (Multi-stage Build)
البناء متعدد المراحل أداة قوية لتحسين حجم الصور. مرحلة البناء تثبت جميع الأدوات والتبعيات، بينما المرحلة النهائية تحتفظ فقط بالملفات اللازمة وقت التشغيل.
# مرحلة البناء
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# مرحلة التشغيل
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/server.js"]5.2 قائمة تحسين الصور
| عنصر التحسين | ما يجب فعله | التأثير |
|---|---|---|
| اختيار صورة أساسية صغيرة | استخدام alpine بدلاً من ubuntu | الصورة من ~200MB إلى ~50MB |
| دمج تعليمات RUN | ربط أوامر متعددة بـ && | تقليل طبقات الصورة |
| استخدام .dockerignore | استبعاد node_modules و.git وغيرها | تسريع البناء، تقليل السياق |
| البناء متعدد المراحل | فصل بيئتي البناء والتشغيل | الصورة النهائية لا تحتوي أدوات البناء |
| تثبيت رقم الإصدار | node:18.17-alpine بدلاً من node:latest | بناء قابل للتكرار |
5.3 ممارسات الأمان
| الممارسة | الوصف |
|---|---|
| عدم التشغيل كـ root | USER node يحدد مستخدم غير root |
| فحص الثغرات | docker scout أو Trivy لفحص الصور |
| الامتيازات الدنيا | تثبيت الحزم الضرورية فقط، بدون أدوات التصحيح |
| عدم تضمين الأسرار | استخدام متغيرات البيئة أو Docker Secrets |
| تحديث الصورة الأساسية بانتظام | إصلاح الثغرات الأمنية في الوقت المناسب |
الخلاصة
حاويات Docker هي البنية التحتية لتسليم البرمجيات الحديثة، وفهمها ضروري لكل مطور.
مراجعة النقاط الرئيسية في هذا الفصل:
- الحاويات مقابل الآلات الافتراضية: الحاويات تشارك نواة المضيف، أخف وأسرع، لكن العزل أقل بقليل من VM
- الثلاثي الأساسي: الصورة (قالب)، الحاوية (نسخة)، المستودع (التوزيع)
- Dockerfile: بناء طبقي، استفد من التخزين المؤقت، التعليمات الأقل تغييراً في البداية
- Docker Compose: تعريف تطبيقات متعددة الخدمات بـ YAML، اسم الخدمة هو اسم المضيف
- ممارسات الإنتاج: بناء متعدد المراحل لتقليل الحجم، صورة أساسية alpine، التشغيل كمستخدم غير root
قراءة إضافية
- التوثيق الرسمي لـ Docker - المرجع الأكثر موثوقية
- Docker Getting Started - البرنامج التعليمي الرسمي للمبتدئين
- Dockerfile Best Practices - دليل أفضل الممارسات الرسمي
- توثيق Docker Compose - مرجع Compose الكامل