شبكات Docker: ربط الحاويات وفهم المنافذ وlocalhost


شبكات Docker تحدد كيف تتواصل الحاويات مع بعضها ومع الجهاز والشبكات الخارجية. أكثر خطأ يربك المبتدئ هو استخدام localhost داخل حاوية للوصول إلى خدمة في حاوية أخرى. يشير هذا العنوان إلى الحاوية نفسها، لذلك تحتاج إلى اسم الخدمة أو عنوان مناسب ضمن الشبكة.
سننشئ شبكة مخصصة ونشغّل خادم Nginx ثم نصل إليه من حاوية أخرى بالاسم. راجع تشغيل Docker للمرة الأولى قبل الدرس إن احتجت. الأمثلة محلية ولم تُنفّذ أثناء إعداد المقال؛ نتائجها المذكورة توقعات تعليمية وليست لقطات اختبار.
ما الشبكة المخصصة في Docker؟
الشبكة المخصصة تجمع حاويات اخترتها أنت ضمن نطاق اتصال. في شبكة bridge يعرّفها المستخدم، يستطيع Docker حل أسماء الحاويات والأسماء المستعارة تلقائيًا، مما يقلل الحاجة إلى حفظ عناوين IP قابلة للتغير.
لا تخلط بينها وبين شبكة bridge الافتراضية القديمة. الاتصال بالأسماء ليس السلوك نفسه في الحالتين. ولهذا سننشئ شبكة باسم واضح بدل الاعتماد على الوضع الافتراضي لمجرد أنه يعمل في مثال صغير.
docker network create g4a-learning-net
docker network ls
يعرض الأمر الثاني الشبكات المتاحة. وجود الشبكة لا يعني اتصال أي حاوية بها بعد؛ يجب اختيارها عند التشغيل أو ربط الحاوية لاحقًا.
شغّل خادمًا داخل الشبكة
أنشئ حاوية Nginx واربطها بالشبكة والمنفذ المحلي:
docker run --name g4a-net-web --network g4a-learning-net -d -p 127.0.0.1:8087:80 nginx:stable
docker ps
docker port g4a-net-web
هنا يوجد مساران مختلفان للوصول. متصفح الجهاز يستخدم http://localhost:8087، بينما تستخدم حاوية في الشبكة نفسها اسم g4a-net-web والمنفذ الداخلي 80. لا تحتاج الحاوية الثانية إلى المرور بالمنفذ المحلي 8087 كي تصل إلى الخادم.
| جهة الطلب | العنوان المناسب في المثال |
|---|---|
| متصفح الجهاز المضيف | http://localhost:8087 |
| حاوية في الشبكة نفسها | http://g4a-net-web:80 |
| الخادم داخل حاويته | localhost يشير إلى الحاوية نفسها |
اختبر اتصال حاوية بحاوية
استخدم حاوية مؤقتة تحتوي wget للوصول إلى صفحة الخادم:
docker run --rm --network g4a-learning-net alpine:3.22 wget -qO- http://g4a-net-web:80
المتوقع ظهور HTML صفحة Nginx إذا كان الخادم يعمل والاسم يُحل داخل الشبكة. هذه تجربة HTTP، بخلاف ping الذي يختبر جانبًا مختلفًا وقد لا يتوفر أصلًا في الصورة.
تُحذف حاوية الاختبار عند انتهاء الأمر بسبب –rm، بينما يستمر الخادم. إذا لم تعمل التجربة، افحص حالة الخادم والشبكة قبل تثبيت أدوات كثيرة داخل صورته. يمكن استخدام حاوية تشخيص مستقلة كما فعلنا هنا.
ماذا تعني صيغة نشر المنافذ؟
الصيغة التي استخدمناها هي عنوان المضيف ثم منفذ المضيف ثم منفذ الحاوية. لذلك 127.0.0.1:8087:80 يجعل الوصول المحلي إلى 8087 يتجه إلى 80 داخل الحاوية.
عدم تحديد عنوان المضيف في -p 8087:80 ينشر المنفذ عادةً على عناوين المضيف الافتراضية، وقد يجعله متاحًا خارج الجهاز بحسب البيئة والجدار الناري. نحدد عنوان loopback في تمارين التعلم لتقييد الوصول المحلي، مع الإبقاء على الحاجة إلى تحديث المحرك ومراجعة الشبكة.
لا تنشر منفذ قاعدة البيانات لمجرد أن التطبيق يحتاج إليها. إذا كانت الخدمات في شبكة Docker نفسها، يمكن للتطبيق الوصول إلى منفذها الداخلي دون نشره للمضيف. انشر فقط ما تحتاج الوصول إليه من خارج شبكة الحاويات.
لماذا يفشل localhost داخل التطبيق؟
لأن localhost داخل الحاوية يرجع إلى مساحة شبكتها المعتادة، لا إلى حاوية قاعدة البيانات. إذا كانت خدمة قاعدة البيانات اسمها db في شبكة مشتركة، يكون اسم المضيف في إعداد التطبيق db.
أما الوصول من الحاوية إلى خدمة على الجهاز المضيف فهو حالة أخرى. يوفر Docker Desktop اسم host.docker.internal لهذا الغرض في البيئات المدعومة، بينما قد تحتاج بيئات Linux إلى إعداد صريح. لا تفترض أن طريقة واحدة تعمل في كل تثبيت.
كذلك يجب أن يستمع خادم التطبيق إلى واجهة مناسبة داخل الحاوية. خادم مربوط بـ127.0.0.1 داخل الحاوية قد لا يقبل اتصالات تأتي من شبكتها حتى لو نشرت المنفذ. راجع إعداد listen أو host في إطار التطبيق.
كيف تفحص شبكات Docker؟
ابدأ بأوامر القراءة التي تكشف اتصال الحاوية بالشبكة:
docker network inspect g4a-learning-net
docker inspect g4a-net-web
docker logs --tail 30 g4a-net-web
يعرض network inspect الحاويات المرتبطة ومعلومات الشبكة. وقد يتضمن inspect تفاصيل إعدادات كثيرة؛ لا تشاركها كاملة دون مراجعة. إذا كان الاسم لا يُحل، تأكد من وجود الطرفين في الشبكة نفسها ومن كتابة الاسم الصحيح.
إذا كان الاسم يُحل لكن الاتصال مرفوض، فابحث عن منفذ خاطئ أو عملية لا تستمع. وإذا كان الطلب يصل ويعيد خطأ HTTP، فقد نجح الاتصال أصلًا وأصبحت المشكلة في التطبيق أو المسار المطلوب.
هل نحتاج host أو none؟
شبكة host تشارك مساحة شبكة المضيف في البيئات التي تدعم هذا النمط، وتختلف آثارها وتوافرها بحسب المنصة. لا تحتاجها لتطبيق ويب محلي متعدد الخدمات. أما none فيعزل الاتصال الشبكي الخارجي مع بقاء تفاصيل مثل loopback داخل الحاوية.
ابدأ بشبكة bridge مخصصة. الانتقال إلى أنماط أخرى يجب أن يجيب عن حاجة محددة، لا أن يكون محاولة عشوائية لإصلاح خطأ أسماء أو منافذ.
إنهاء التمرين
أوقف حاوية الخادم واحذفها، ثم احذف شبكة التدريب بعد خلوّها من الحاويات:
docker stop g4a-net-web
docker rm g4a-net-web
docker network rm g4a-learning-net
عند فهم شبكات Docker، ابدأ كل تشخيص بسؤالين: من يرسل الطلب، وأين توجد الخدمة؟ الإجابة تحدد الاسم والمنفذ الصحيحين وتمنع الخلط بين localhost على الجهاز وlocalhost داخل الحاوية.
أسئلة شائعة
هل يجب نشر منفذ لكل حاوية؟
لا. الخدمات المتصلة بشبكة مشتركة تتواصل بالمنافذ الداخلية. تحتاج النشر عندما تريد الوصول من المضيف أو خارجه.
هل تعمل أسماء الحاويات في كل شبكة؟
شبكات bridge المخصصة توفر حل الأسماء تلقائيًا. لا تفترض السلوك نفسه في شبكة bridge الافتراضية.
هل EXPOSE يكفي للوصول من المتصفح؟
لا. تحتاج إعداد نشر منفذ أو مسار وصول آخر مناسب.
لماذا تتغير عناوين IP؟
قد تتغير عند إعادة إنشاء الحاوية. استخدم أسماء الخدمات في الشبكة بدل ربط إعدادات التطبيق بعنوان مؤقت.
المصادر والمراجعة التقنية
استُلهم ترتيب موضوعات السلسلة من ملاحظات Narayan Prasad (@code.withnarayan). الشرح العربي والأمثلة والرسوم هنا إعداد مستقل، مع الرجوع إلى الوثائق الرسمية لتصحيح وتوسيع المفاهيم.


