Docker Ports, localhost و Service Discovery فـ موديل واحد
النشر والأدواتشرح مفصل على الفرق بين ports لي كنفتحو فـ host، و namespace ديال container، وكيفاش Compose DNS كيخدم باش يتواصلو services بيناتهم.
فهاد المقال
كيفاش نفهمو الـ Networking فـ Docker
أكبر غلط كيوقعو فيه الناس فـ البداية هو مكيفرقوش بين فين السيرفيس كيكون خدام (listening) وكيفاش كنوصلو ليه. باش تفهم هادشي، خاصك تفرق بين الـ Host Network والـ Container Network Namespace.
كل container كيكون عندو namespace ديالو بوحدو. هادشي كيعني أن عندو interface réseau virtuelle و loopback address (127.0.0.1) ديالو. إلا كان شي برنامج وسط container خدام فـ localhost:8080 ، راه خدام فـ loopback ديال داك container ماشي ديال الماكينة (host). يعني إلا جربتي تدخل لـ localhost:8080 من browser فـ الماكينة ديالك، ما غاديش تخدم حيت loopback ديال host بوحدو وديال container بوحدو.
Port Mapping: القنطرة لي كتربطهم
فـ Compose bridge العادي، 5332:5432 كتربط host port 5332 بـ container port 5432. Process خاصها فعلا تسمع فداك port وinterface مناسبة بحال 0.0.0.0. EXPOSE غير documentation، ما كتخلقش listener ولا publishing. إلا process مربوطة غير بـ loopback ديال container، publishing تقدر ما تخدمش.
فـ local development DB استعمل 127.0.0.1:5332:5432؛ بلا address تقدر تتنشر فـ كاع interfaces ديال host. Containers فنفس Compose network كيوصلو لـ db:5432 بلا DB port منشورة. هاد الشرح كيتعلق بالـ bridge العادية، ماشي host networking ولا shared namespace.
Service Discovery والتواصل الداخلي
الـ port mapping مهم للمطور ولا للمستخدم لي برا، ولكن بالنسبة لـ containers لي فـ نفس الـ network، هادشي ما كيهمهمش.
ملي كنخدمو بـ Docker Compose، Docker كيصاوب bridge network. كل service فـ docker-compose.yml كيولي عندو DNS entry بسميتو. الـ containers كيهضرو مع بعضياتهم باستعمال هاد السميات و الـ ports الداخلية، بلا ما يدوزو من الـ network ديال host.
مثال تطبيقي: Search API و Database
نتخيلو عندنا Search API (مخدومة بـ Java/Spring) خاصها تكونيكطا مع PostgreSQL database.
Configuration (docker-compose.yml مثال توضيحي)
services:
db:
image: postgres:15
ports:
- "127.0.0.1:5332:5432"
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD:?Set DB_PASSWORD locally}
search-api:
image: search-api:latest
ports:
- "8088:8080"
environment:
# ركز هنا: كنستعملو سمية السيرفيس 'db' والـ port الداخلي 5432
SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/postgres
SPRING_DATASOURCE_USERNAME: postgres
SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD:?Set DB_PASSWORD locally}
depends_on:
- db
تحليل كيفاش كيدوز الـ Traffic
- User → API: المستخدم كيدخل لـ
http://localhost:8088. الـ host كيصيفط request لـ container ديالsearch-apiفـ port8080. - API → Database: الـ
search-apiمحتاجة data. كتقلب على hostname سميتوdbعن طريق DNS ديال Docker، كتعرف الـ IP الداخلي ديال container، وكتكونيكطا لـ port5432. ما كتستعملشlocalhost:5332حيتlocalhostوسط container ديال API كيعني API براسها ماشي الـ host. - Developer → Database: المطور كيستعمل tool (بحال pgAdmin) فـ الماكينة ديالو. كيكونيكطا لـ
localhost:5332. Docker كيصيفط هادشي لـ container ديالdbفـ port5432.
حالات فين كيوقع مشكل (Failure Cases)
- إلا درتي
localhost:5432فـ config ديال API: الـ API غادي تقلب على Postgres وسط container ديالها هي. وبما أن Postgres ما كاينش تما، غادي تعطيك connection refused. - إلا درتي
localhost:5332فـ config ديال API: الـ API غادي تقلب على شي حاجة خدامة فـ port 5332 وسط container ديالها. حتى هادي ما غاديش تخدم. - إلا حيدتي
portsمن السيرفيسdb: الـ API غتبقى تخدم عادي حيت راهم فـ نفس الـ network. ولكن المطور ما غاديش يقدر يكونيكطا بـ tool من الماكينة حيت ما بقاتش القنطرة (mapping).
تمرين تطبيقي
السيناريو: عندك service سميتها cache خدامة فـ port 6379 و service سميتها app خدامة فـ port 80. بغيتي app توصل لـ cache ، وبغيتي تقدر تخدم redis-cli من الماكينة ديالك باش تشوف شنو كاين فـ cache.
الأسئلة:
- شنو خاص يكون الـ
portsmapping ديال servicecacheفـdocker-compose.yml؟ - شنو هي connection string لي خاص
appتستعمل باش توصل لـcache؟ - إلا بدلتي mapping لـ
7000:6379، واش connection string ديالappغادي تبدل ؟
الأجوبة:
6379:6379(أو أي port آخر فـ host).cache:6379.- لا. الـ
appكتخدم بالـ network الداخلي؛ ما كيهمهاش الـ port لي مفتوح فـ host (7000).