دليل المطورين إلى Docker: الصور والحاويات وCompose
ربما سمعت عن Docker والحاويات، لكن عند محاولة استخدامه تجد نفسك غارقاً في مصطلحات مثل الصور (images) والحاويات (containers) والأحجام (volumes) وCompose. أو ربما تستخدم Docker بالفعل لكن صورك ضخمة، والبناء بطيء، وإدارة خدمات متعددة تبدو كعبء ثقيل. هذا الدليل يقطع الطريق على كل هذا التشويش. سنغطي أساسيات Docker للمطورين، مع التركيز على ما تحتاج فعلاً معرفته لبناء وتشغيل وإدارة تطبيقات معبأة في حاويات بكفاءة.
لماذا Docker؟ المشكلة التي يحلها
قبل Docker، كان نشر تطبيق يعني مطابقة البيئة بدقة: إصدارات نظام تشغيل محددة، ومكتبات، وإعدادات. أصبحت عبارة "يعمل على جهازي" مبتذلة لأنها كانت صحيحة. يحل Docker هذه المشكلة عبر تغليف تطبيقك مع تبعياته في وحدة واحدة قابلة للنقل تسمى حاوية (container). الحاويات خفيفة ومعزولة وتعمل بشكل متسق في أي مكان يُثبَّت فيه Docker.
الصور مقابل الحاويات: الفرق الجوهري
الصورة (image) هي قالب للقراءة فقط يحتوي على كود تطبيقك وبيئة التشغيل والمكتبات والإعدادات. الحاوية (container) هي نسخة قيد التشغيل من الصورة. تخيل الصورة كصنف (class) والحاوية ككائن (object). يمكنك تشغيل عدة حاويات من نفس الصورة، كل واحدة معزولة عن الأخرى.
كيف تُبنى الصور
تُبنى الصور من ملف Dockerfile، وهو ملف نصي يحتوي على تعليمات. إليك مثالاً بسيطاً لتطبيق Node.js:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
كل تعليمة تُنشئ طبقة (layer). تُخزَّن الطبقات مؤقتاً، لذا إذا غيّرت كود المصدر فقط، يعيد Docker استخدام الطبقات المخزنة للتبعيات، مما يجعل إعادة البناء سريعة.
البناء والتشغيل
ابنِ الصورة وشغّل حاوية:
docker build -t my-app .
docker run -p 3000:3000 my-app
الخيار -p يربط المنفذ 3000 على المضيف بالمنفذ 3000 داخل الحاوية.
أفضل الممارسات لصور Docker فعالة
الصور الكبيرة تبطئ عمليات البناء والدفع والنشر. اتبع هذه الممارسات للحفاظ على صور نحيفة:
- استخدم صوراً أساسية رسمية نحيفة أو alpine عند الإمكان. مثلاً،
node:18-alpineأصغر بكثير منnode:18. - استفد من البناء متعدد المراحل (multi-stage builds) لفصل تبعيات وقت البناء عن وقت التشغيل. هذا يبقي الصورة النهائية ضئيلة.
- اجمع أوامر RUN لتقليل الطبقات ونظّف ذاكرات التخزين المؤقت لمدير الحزم في نفس الطبقة.
- استخدم ملف .dockerignore لاستبعاد الملفات غير الضرورية (مثل node_modules و.git) من سياق البناء.
إليك Dockerfile متعدد المراحل لتطبيق Go:
# Build stage
FROM golang:1.21-alpine AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app/main .
# Final stage
FROM alpine:latest
COPY --from=builder /app/main /main
CMD ["/main"]
تحتوي الصورة النهائية فقط على الملف التنفيذي المُجمَّع وAlpine، وليس سلسلة أدوات Go.
إدارة البيانات باستخدام الأحجام (Volumes)
الحاويات مؤقتة؛ عند حذفها تُفقد بياناتها. الأحجام (Volumes) تحفظ البيانات خارج دورة حياة الحاوية. استخدمها لقواعد البيانات والرفع وأي حالة يجب أن تبقى بعد إعادة التشغيل.
docker run -v my-data:/var/lib/postgresql/data postgres
هذا ينشئ حجماً مسمّى my-data يديره Docker. للتطوير، يمكنك أيضاً ربط كود المصدر داخل الحاوية لإعادة التحميل المباشر:
docker run -v $(pwd):/app -p 3000:3000 my-app
Docker Compose: تنسيق حاويات متعددة
غالباً ما تحتاج التطبيقات الحقيقية خدمات متعددة: خادم ويب، وقاعدة بيانات، وذاكرة تخزين مؤقت. تشغيل كل منها عبر docker run أمر ممل وعرضة للأخطاء. يتيح لك Docker Compose تعريف وتشغيل تطبيقات متعددة الحاويات بملف YAML واحد.
ملف docker-compose.yml عملي
إليك ملف Compose لتطبيق Node.js مع PostgreSQL وRedis:
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/mydb
- REDIS_URL=redis://cache:6379
depends_on:
- db
- cache
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- postgres_data:/var/lib/postgresql/data
cache:
image: redis:7-alpine
volumes:
postgres_data:
شغّل docker compose up لبدء جميع الخدمات. ينشئ Compose شبكة افتراضية بحيث يمكن للحاويات الوصول إلى بعضها البعض باسم الخدمة (مثل db وcache).
أوامر Compose الشائعة
docker compose up -d– البدء في الوضع المنفصل (في الخلفية).docker compose logs -f web– متابعة سجلات خدمة معينة.docker compose exec web sh– فتح صدفة (shell) في حاوية قيد التشغيل.docker compose down– إيقاف وإزالة الحاويات والشبكات والأحجام (ما لم تكن الأحجام خارجية).
متى تستخدم Docker Compose مقابل Kubernetes
Docker Compose مثالي للتطوير المحلي والاختبار والنشر الصغير. أما Kubernetes فيتفوق في تنسيق الحاويات عبر العناقيد (clusters) للإنتاج على نطاق واسع. لكثير من المطورين، يكفي Compose للعمل اليومي، ويمكنك الانتقال إلى Kubernetes عندما تحتاج إلى التوسع التلقائي والاستشفاء الذاتي والشبكات المتقدمة.
| الميزة | Docker Compose | Kubernetes |
|---|---|---|
| حالة الاستخدام | التطوير المحلي، النشر الصغير | عناقيد الإنتاج |
| التعقيد | منخفض | مرتفع |
| التوسع | يدوي | تلقائي |
| منحنى التعلم | لطيف | حاد |
الأسئلة الشائعة
ما الفرق بين الصورة والحاوية؟
الصورة قالب للقراءة فقط يحتوي على تطبيقك وتبعياته. الحاوية نسخة قيد التشغيل من الصورة. يمكنك تشغيل عدة حاويات من صورة واحدة.
كيف أقلل حجم صورة Docker؟
استخدم صوراً أساسية أصغر (مثل Alpine)، والبناء متعدد المراحل، واجمع أوامر RUN، واستخدم ملف .dockerignore لاستبعاد الملفات غير الضرورية.
هل يمكنني استخدام Docker Compose في الإنتاج؟
نعم، لعمليات النشر صغيرة النطاق. أما للبيئات الأكبر والديناميكية، فإن Kubernetes أو Docker Swarm أكثر ملاءمة.
هل أنت مستعد لتحسين سير عمل Docker لديك؟ اطّلع على محلل سجلات Nginx لتصحيح ومراقبة خوادم الويب المعبأة في حاويات.