الدرس 1 من 15 · الأساسيات
لماذا الحاويات؟
الهدف
أن تفهم المشكلة التي يحلّها Docker، وما هي الحاوية (conteneur) حقاً، وأن تتقن المفردات الأساسية: الصورة (image)، الحاوية، السجل (registre)، Docker Engine وOCI. هذا الدرس لا يتطلب أي تثبيت.
أهم النقاط
- الحاوية هي عملية Linux معزولة: لها رؤيتها الخاصة للملفات والشبكة وباقي العمليات، لكنها تستعمل نواة الجهاز المضيف.
- الصورة قالب ثابت وللقراءة فقط (البرنامج، ومكتباته، وإعداداته). يمكن تشغيل ما نشاء من الحاويات انطلاقاً من الصورة نفسها.
- السجل يخزّن الصور ويوزّعها (Docker Hub، GitHub Container Registry، سجل خاص).
- Docker Engine هو المحرّك: خدمة خلفية (démon) اسمها
dockerdتبني الصور وتشغّل الحاويات، ويُتحكَّم فيها بواسطة الأمرdocker. - معيار OCI (Open Container Initiative) يصف صيغة الصور وطريقة تشغيلها: الصورة المبنية بـ Docker تعمل أيضاً مع Podman أو containerd أو Kubernetes.
المشكلة: « إنه يعمل على جهازي »
تخيّل متجراً إلكترونياً في الدار البيضاء. كتب المطوّر موقعه بـ Node.js 22 على حاسوبه المحمول بنظام Ubuntu. أما خادم الإنتاج فيعمل بنظام Debian مع Node.js 18. ويوم الإطلاق، ترفض مكتبةٌ الإقلاع: إصدار Node غير مطابق، وحزمة نظام ناقصة، ومتغيّر بيئة منسيّ.
لهذه المشكلة ثلاثة أسباب كلاسيكية:
- التبعيات تختلف من جهاز إلى آخر (إصدارات اللغة، مكتبات النظام).
- الإعدادات غير مكتوبة بوضوح: إنها في رأس شخص ما.
- عدة تطبيقات على الخادم نفسه يزعج بعضها بعضاً (أحدها يريد PHP 8.1، والآخر PHP 8.3).
الحاوية تعالج هذه النقاط الثلاث: التطبيق يسافر مع كل ما يحتاجه، والوصفة مكتوبة في ملف (الـ Dockerfile)، ولكل تطبيق فضاؤه الخاص، معزولاً عن الآخرين.
الجهاز الافتراضي مقابل الحاوية
الجهاز الافتراضي (VM) يحاكي حاسوباً كاملاً: معالجاً افتراضياً، وقرصاً افتراضياً، وخاصة نظام تشغيله الخاص بنواته الخاصة. ويتولى المُشرف الافتراضي (hyperviseur) مثل VMware وKVM وHyper-V وVirtualBox تقاسم العتاد بين الأجهزة الافتراضية.
أما الحاوية فلا تحاكي شيئاً. إنها عملية عادية في النظام المضيف، تحبسها نواة Linux بفضل آليتين:
- فضاءات الأسماء (namespaces): للعملية قائمة عملياتها الخاصة (
pid)، وشبكتها الخاصة (net)، ونقاط تركيبها الخاصة (mnt)، واسم مضيفها الخاص (uts)، ومستخدموها الخاصون (user)…؛ - مجموعات التحكم (cgroups): تحدّ النواة من الذاكرة والمعالج وعمليات الإدخال والإخراج التي يمكن لهذه العملية استهلاكها.
| المعيار | الجهاز الافتراضي | الحاوية |
|---|---|---|
| ما الذي يُعزل | جهاز كامل | عملية (وأبناؤها) |
| النواة | نواة لكل VM | نواة المضيف، مشتركة |
| الحجم المعتاد | عدة غيغابايتات | من بضعة ميغابايتات إلى بضع مئات منها |
| الإقلاع | عشرات الثواني | جزء من الثانية |
| الأنظمة الممكنة | أي نظام (Windows داخل Linux…) | برامج Linux على نواة Linux |
| الكثافة | بضعة أجهزة افتراضية لكل خادم | عشرات أو مئات الحاويات |
| العزل | قوي جداً (عتاد افتراضي) | جيد، لكنه يعتمد على النواة المشتركة |
لا تتعارض التقنيتان. ففي الواقع، كثيراً ما نستأجر جهازاً افتراضياً (VPS لدى مزوّد استضافة) ونشغّل عليه حاويات.
في Windows وmacOS لا توجد نواة Linux. لذلك يُقلع Docker Desktop جهازاً افتراضياً صغيراً بنظام Linux في الخلفية، وتعمل حاوياتك بداخله.
يمكنك رؤية فضاءات الأسماء لأي عملية Linux، حتى بدون Docker:
ls /proc/self/ns # فضاءات الأسماء الخاصة بالـ shell الحالي
# cgroup ipc mnt net pid pid_for_children time time_for_children user uts
cat /proc/self/cgroup # مجموعة التحكم التي ينتمي إليها
uname -r # النواة: هي نفسها للمضيف ولكل حاوياته
الصورة والحاوية
أفضل صورة ذهنية هي صورة الصنف (classe) والكائن (objet) في البرمجة، أو القالب والكعكة:
- الصورة هي القالب: غير قابلة للتغيير، ذات إصدارات، قابلة للمشاركة؛
- الحاوية كعكة خرجت من القالب: نسخة حيّة، تُقلع وتعمل وتتوقف ويمكن حذفها.
تتكوّن الصورة من طبقات (couches) مكدّسة. كل طبقة تضيف ملفات أو تعدّلها أو تحذفها مقارنة بالطبقة السابقة. وعندما تُقلع حاوية، يضع Docker فوقها طبقة رقيقة قابلة للكتابة، خاصة بهذه الحاوية. والنتيجة بالغة الأهمية:
كل ما تكتبه الحاوية في طبقتها يختفي عند حذفها. البيانات التي يجب الاحتفاظ بها (قاعدة بيانات، ملفات يرسلها الزبائن) توضع في وحدة تخزين (volume). سترى ذلك بالتفصيل في المستوى 2.
مبدآن يوجّهان استعمال الصور:
- الصورة لا تُعدَّل. لتغيير شيء ما، نبني صورة جديدة (إصداراً جديداً)، ونحذف الحاوية القديمة ونشغّل حاوية جديدة.
- حاوية واحدة، دور واحد. موقع الويب في حاوية، وقاعدة PostgreSQL في أخرى، وذاكرة التخزين المؤقت Redis في ثالثة. ثم نجمعها بواسطة Docker Compose.
السجلات واسم الصورة
السجل خادم يخزّن الصور، مثل مستودع حزم apt أو dnf تقريباً. Docker Hub هو السجل العام الافتراضي. وتوجد سجلات أخرى كثيرة: GitHub Container Registry (ghcr.io)، وسجلات السحابات (Amazon ECR، Azure ACR، Google)، وGitLab، وHarbor… ويمكنك استضافة سجلّك الخاص.
يتكوّن الاسم الكامل للصورة من ثلاثة أجزاء:
ghcr.io / startup-rabat/api : 2.3.1
└──┬──┘ └──────┬────────┘ └─┬─┘
registre dépôt étiquette (tag)
(registre = السجل، dépôt = المستودع، étiquette = الوسم.)
عندما ينقص جزء، يكمله Docker:
| ما تكتبه | ما يفهمه Docker |
|---|---|
nginx |
docker.io/library/nginx:latest |
nginx:1.27-alpine |
docker.io/library/nginx:1.27-alpine |
ecole/inscriptions:2.0 |
docker.io/ecole/inscriptions:2.0 |
ghcr.io/startup-rabat/api:2.3.1 |
(الاسم كامل أصلاً) |
- بدون سجل:
docker.io(Docker Hub). - بدون فضاء أسماء:
library/، مجلد الصور الرسمية (nginx، postgres، redis، node، debian…). - بدون وسم:
latest. هذه الكلمة لا تعني « الأحدث »: إنها فقط الوسم الافتراضي. في الإنتاج، اكتب دائماً وسماً محدداً.
Docker Engine: من يفعل ماذا؟
عندما تكتب docker run nginx، تعمل عدة برامج معاً:
vous ──> docker (client, la commande)
│ API REST sur /var/run/docker.sock
▼
dockerd (le démon Docker Engine)
│ images, réseaux, volumes, construction (BuildKit)
▼
containerd ──> runc ──> le processus isolé (votre conteneur)
dockerهو العميل (client): لا ينفّذ شيئاً بنفسه، بل يرسل أوامر إلى الواجهة البرمجية (API) للخدمة الخلفية. ويمكنه حتى التحدث إلى خدمة خلفية بعيدة.dockerdهو الخدمة الخلفية (démon): يدير الصور والشبكات ووحدات التخزين والبناء.containerdيدير دورة حياة الحاويات، و**runc** يُنشئ فعلياً العملية المعزولة (فضاءات الأسماء، cgroups).
تعمل الخدمة الخلفية بصلاحيات root. لذلك فمن يستطيع التحدث إلى المقبس (socket) الخاص بها يستطيع فعل كل شيء على الجهاز: سترى في المستوى 4 ما يعنيه ذلك بالنسبة للأمان.
OCI: معيار مفتوح
في عام 2015، أنشأت Docker وجهات فاعلة أخرى Open Container Initiative. وهي تنشر مواصفات مفتوحة:
- image-spec: صيغة الصورة (الطبقات، البيان manifeste، الإعدادات)؛
- runtime-spec: كيفية تشغيل حاوية انطلاقاً من صورة مفكوكة الضغط؛
- distribution-spec: كيف يستقبل السجل الصور ويوزّعها.
بفضلها، لست سجين أداة واحدة. فالصورة التي بناها Docker على حاسوب مطوّر محمول يمكن أن يشغّلها Podman على خادم Red Hat، أو containerd داخل Kubernetes، أو أن تُخزَّن في أي سجل متوافق.
لماذا أصبح Docker لا غنى عنه
| الحاجة | ما يقدّمه Docker |
|---|---|
| تثبيت تطبيق في 5 دقائق | docker run لصورة رسمية، لا شيء للترجمة (compilation) |
| إعادة إنتاج خلل من الإنتاج | تشغيل الصورة نفسها بالضبط محلياً |
| النشر كثيراً وبدون مخاطرة | صورة جديدة = إصدار جديد؛ التراجع = إعادة تشغيل القديمة |
| جعل الإصدارات تتعايش | PHP 8.1 وPHP 8.3 في حاويتين، على الخادم نفسه |
| التكامل المستمر (CI) | كل اختبار يُقلع في بيئة نظيفة ومطابقة |
| التحضير لـ Kubernetes | Kubernetes ينسّق… حاويات مبنية كما هنا |
مثال ملموس: يتكوّن تطبيق التسجيل في مدرسة بفاس من موقع ويب وواجهة برمجية (API) وقاعدة PostgreSQL. مع Docker، ينسخ مطوّر جديد المشروع، ويكتب أمراً واحداً (docker compose up)، فيحصل في دقيقة واحدة على المجموعة نفسها الموجودة في الإنتاج.
شيء من التاريخ
لم تولد الحاويات مع Docker. إنها ثمرة عشرين سنة من الإضافات إلى عالم Unix ونواة Linux:
| السنة | المرحلة |
|---|---|
| 1979 | chroot في Unix: عملية ترى مجلداً آخر كجذر / |
| 2000 | الـ jails في FreeBSD: عزل العمليات والشبكة |
| 2004 | الـ zones في Solaris |
| 2002-2013 | فضاءات الأسماء تصل تباعاً إلى نواة Linux؛ والـ cgroups (التي اقترحتها Google) تدخلها في 2008 |
| 2008 | LXC: أولى حاويات Linux الكاملة، لكنها صعبة الاستعمال |
| 2013 | Docker: أمر بسيط، وصور بطبقات، وسجل عام |
| 2015 | إنشاء OCI؛ Kubernetes 1.0 |
| 2017-2019 | Docker تعهد بـ containerd إلى مؤسسة CNCF؛ ظهور Podman (Red Hat) |
| اليوم | Docker Engine وPodman وcontainerd وKubernetes تتقاسم صيغة الصور نفسها |
الثورة الحقيقية لـ Docker لم تكن تقنية: بل كانت في تغليف هذه الآليات في أداة بسيطة، مع صيغة صور قابلة للنقل وسجل يتشارك فيه الجميع صورهم.
Docker أم Podman أم containerd: أيّها أستعمل؟
ستصادف عدة أدوات. كلها تتحدث لغة الصور نفسها:
| الأداة | ما هي | أين نصادفها |
|---|---|---|
| Docker Engine | خدمة خلفية + العميل docker، وCompose، وBuildKit |
خوادم Debian/Ubuntu، الـ VPS، حواسيب المطوّرين |
| Docker Desktop | تطبيق رسومي بجهاز افتراضي Linux مدمج | حواسيب Windows وmacOS |
| Podman | الأوامر نفسها التي في Docker، بدون خدمة خلفية، مع وضع rootless أصلي | RHEL، Rocky، AlmaLinux، Fedora |
| containerd | محرّك منخفض المستوى، بدون واجهة سهلة الاستعمال | تحت Docker، وفي أغلب عناقيد Kubernetes |
يستعمل هذا الدرس Docker Engine وDocker Compose، وهما الأكثر انتشاراً لدى مزوّدي الاستضافة وفي عروض الشغل. وكل ما تتعلّمه عن الصور وملفات Dockerfile صالح أيضاً لـ Podman.
المفردات في لمحة
| الكلمة | تعريف مختصر |
|---|---|
| الصورة (Image) | قالب للقراءة فقط، مكوّن من طبقات، يُعرَّف باسم ووسم |
| الحاوية (Conteneur) | نسخة قيد التشغيل من صورة، مع طبقة قابلة للكتابة يمكن التخلص منها |
| الطبقة (layer) | مجموعة تعديلات على الملفات، مشتركة بين الصور |
| السجل (Registre) | خادم يخزّن الصور ويوزّعها |
| المستودع (repository) | مجموعة إصدارات الصورة نفسها داخل سجل |
| الوسم (tag) | اسم إصدار: 1.27، 1.27-alpine، latest |
| Dockerfile | وصفة نصية تصف كيفية بناء صورة |
| وحدة التخزين (Volume) | فضاء تخزين يديره Docker، يبقى بعد زوال الحاويات |
| Compose | أداة تصف عدة حاويات وتشغّلها بواسطة ملف YAML |
أخطاء متكررة
- الاعتقاد أن الحاوية جهاز افتراضي صغير: ليست لها نواتها الخاصة. وحدة النواة (module noyau) أو الإعداد
sysctlالعام يتمّ على المضيف. - تخزين بيانات مهمة داخل الحاوية: تختفي عند الحذف. استعمل وحدة تخزين.
- استعمال
latestفي الإنتاج: لن تعرف أي إصدار يعمل، ومجرد إعادة تشغيل قد تغيّر الإصدار. - أخذ أي صورة من Docker Hub: فضّل الصور الرسمية أو صور الناشرين الموثَّقين، كما تختار مستودع حزم موثوقاً.
التطبيق العملي (Lab)
Docker غير مثبّت في المختبر: لا حاجة إليه هنا. ستقوم بما يلي:
- سرد فضاءات الأسماء لعملية ما، وهي اللبنة الأساسية للحاوية؛
- تسجيل إصدار النواة، التي ستتقاسمها كل حاويات الجهاز؛
- كتابة الاسم الكامل لصورة رسمية؛
- تفكيك اسم صورة مستضافة في GitHub Container Registry.
اختبار قصير
- ما الفرق الجوهري بين الجهاز الافتراضي والحاوية؟
- ما الآليتان في نواة Linux اللتان تعزلان الحاوية وتحدّان من مواردها؟
- ماذا يحدث لملف كتبته حاوية في طبقتها الخاصة عندما نحذف هذه الحاوية؟
- ما الاسم الكامل الذي يستعمله Docker لـ
redis؟ - ما فائدة معيار OCI بالنسبة لمقاولة؟
الأجوبة
- الجهاز الافتراضي يحمل نظامه الخاص ونواته الخاصة على عتاد افتراضي؛ أما الحاوية فهي عملية معزولة في المضيف، تتقاسم نواة المضيف.
- فضاءات الأسماء (namespaces) للعزل، ومجموعات التحكم (cgroups) للحدّ من الموارد.
- يضيع. البيانات التي يجب الاحتفاظ بها يجب أن توضع في وحدة تخزين أو مجلد مُركَّب.
docker.io/library/redis:latest.- يضمن أن الصورة غير مرتبطة بأداة واحدة: إذا بُنيت بـ Docker، يمكنها أن تعمل مع Podman أو containerd أو Kubernetes، وأن تُخزَّن في أي سجل متوافق.
المراجع: التوثيق الرسمي لـ Docker (docs.docker.com، رخصة Apache 2.0). نص أصلي من MasterLinux.