شبكات Docker وتحويل المنافذ
كيف ترى الحاويات بعضها البعض، وكيف يختلف نشر المنفذ عن EXPOSE المجرد، ولماذا يتجاوز Docker قواعد ufw.
آخر تحديث 23 أغسطس 2026
نصف مشكلات الحاويات متعلقة بالشبكة: خدمة لا تستطيع الوصول إلى قاعدة البيانات، منفذ مشغول، لوحة التحكم أصبحت فجأة مكشوفة للإنترنت بأكمله. لنفصّل كيف يعمل ذلك.
ثلاثة أنواع من الشبكات
- bridge — النوع الافتراضي. تحصل الحاويات على عناوين داخلية وتتواصل فيما بينها، وتخرج عبر NAT الخاص بالمضيف.
- host — تستخدم الحاوية شبكة المضيف مباشرة، فلا حاجة لنشر المنافذ ولا يعمل أصلًا. سريع، لكن بلا عزل: المنفذ 80 في الحاوية هو المنفذ 80 في المضيف.
- none — لا شبكة على الإطلاق. للمهام التي لا تحتاج إليها.
تختلف الشبكة المخصصة التي تنشئها أنت أو ينشئها Compose عن شبكة bridge الافتراضية في أمر مهم واحد: تحليل الأسماء يعمل فيها. تستطيع حاوية app الوصول إلى حاوية db بالاسم db.
docker network create backend
docker network ls
docker network inspect backend
في Compose، تُنشأ هذه الشبكة تلقائيًا لكل مشروع.
نشر المنافذ
ports:
- "127.0.0.1:8080:8080" # accessible only from the machine itself
- "80:80" # accessible to the whole internet
على اليسار المنفذ في المضيف، وعلى اليمين المنفذ داخل الحاوية. لا تنشر توجيهة EXPOSE في الصورة أي شيء: فهي مجرد ملاحظة عن المنفذ الذي يستمع عليه التطبيق.
القاعدة بسيطة: انشر فقط ما يجب أن يكون متاحًا من الخارج. قاعدة البيانات ولوحة التحكم وواجهة API الداخلية توضع على 127.0.0.1، وخادم الويب مع الشهادة يكشفها للخارج.
يكتب Docker قواعد
iptablesبنفسه، ويفعل ذلك قبل السلاسل التي يديرهاufw. المنفذ المنشور بصيغة-p 8080:8080سيكون متاحًا من الإنترنت حتى لو أظهرufwحالة “deny”. لا تعتمد على الجدار الناري — اربط المنفذ بـ127.0.0.1.
التواصل بين الحاويات
services:
app:
networks: [frontend, backend]
db:
networks: [backend]
proxy:
networks: [frontend]
ports:
- "80:80"
- "443:443"
networks:
frontend:
backend:
هنا تكون قاعدة البيانات متاحة للتطبيق فقط، ولا يواجه الخارج سوى خادم الويب. هذا هو الإعداد الصحيح لأي حزمة خدمات.
داخل الحاوية، أشر إلى الجارة باسم خدمتها: postgres://db:5432/app. العنوان localhost داخل الحاوية يعني الحاوية نفسها، لا المضيف — وهو ثاني أكثر خطأ شائع بعد latest.
للوصول من حاوية إلى خدمة تعمل على المضيف نفسه، استخدم الاسم host.docker.internal بإضافة:
extra_hosts:
- "host.docker.internal:host-gateway"
التشخيص
docker compose exec app ping -c2 db
docker compose exec app getent hosts db
sudo ss -tulpn | grep LISTEN
docker port <container>
سيُظهر ss الواجهة التي يستمع عليها المنفذ فعليًا: 0.0.0.0:8080 — مفتوح للخارج، 127.0.0.1:8080 — لا.
الأخطاء الشائعة
- “المنفذ مستخدم بالفعل”. يشغله حاوية أخرى أو خدمة على المضيف. سيجد
sudo ss -tulpn | grep :80المتسبب. - حاويات في مشاريع Compose مختلفة لا ترى بعضها. لكل مشروع شبكته الخاصة. اربطها صراحةً عبر
networks: { shared: { external: true } }. - التطبيق يستمع على
127.0.0.1داخل الحاوية. عندها لن يفيد النشر: لا يمكن الوصول إليه من خارج الحاوية. اضبط التطبيق ليستمع على0.0.0.0. - عرض النطاق. حتى 500 Mbps مشتركة لكل مضيف. توزيع الملفات يتقاسمها مع كل شيء آخر.