شبکه در Docker Compose

فصل 1 — شبکه در Docker چیست؟

وقتی چند کانتینر اجرا می‌کنی، آن‌ها باید بتوانند:

  • با هم حرف بزنند
  • ولی هر چیزی نباشد به هر چیزی دسترسی داشته باشد
  • معماری‌ات امن و تمیز باشد

Docker دقیقاً مثل یک WiFi خصوصی برای کانتینرها شبکه ایجاد می‌کند.

هر کانتینر:

  • یک IP می‌گیرد
  • نامش به عنوان hostname شناخته می‌شود
  • می‌تواند سرویس‌های دیگر را با اسمشان صدا بزند
نام سرویس = hostname = آدرس شبکه داخلی

فصل 2 — رفتار پیش‌فرض Compose

اگر یک فایل Compose داشته باشی، Docker خودش یک شبکه می‌سازد:

myproject_default

و همه سرویس‌ها داخل آن هستند.

مثال:

services:
  api:
    image: myapi
  db:
    image: postgres

در شبکه:

hostname: api → 172.x.x.x
hostname: db  → 172.x.x.x

در کد API:

DB_HOST=db

تمام.

هیچ port mapping داخلی لازم نیست.

فصل 3 — ارتباط داخلی vs ارتباط بیرونی

مفهوم توضیح
Network ارتباط کانتینر ←→ کانتینر
Ports ارتباط بیرون ←→ کانتینر (مثلاً مرورگر → API)

یعنی:

ports:
  - "5432:5432"

فقط دسترسی از کامپیوترت به Postgres را می‌دهد، نه دسترسی کانتینرهای دیگر.

ارتباط کانتینرها فقط و فقط از طریق network است.

فصل 4 — ساختن شبکه‌های جداگانه (Isolation)

این از مهم‌ترین بخش‌هاست.

شبیه خانه با دو منطقه:

  • پذیرایی (مهمان فقط همین را می‌بیند)
  • اتاق خواب (خصوصی)

در Docker:

services:
  nginx:
    networks:
      - public

  api:
    networks:
      - public
      - private

  db:
    networks:
      - private

networks:
  public:
  private:

نتیجه:

✔ nginx → api
✘ nginx → db
✔ api → db

معماری استاندارد وب دقیقاً همین است.

فصل 5 — Network Aliases (اسم مستعار شبکه)

این بخش برای load balancing یا داشتن نام مشترک برای چند سرویس استفاده می‌شود.

دو API داری:

services:
  api1:
    networks:
      backend:
        aliases:
          - app

  api2:
    networks:
      backend:
        aliases:
          - app

networks:
  backend:

در شبکه Docker:

app → api1
app → api2

یعنی اگر یک سرویس بگوید:

curl http://app:3000

Docker یکی از این دو را انتخاب می‌کند.

مثل یک دامنه:

app.local → سرور A
app.local → سرور B

چند سرویس → یک hostname

فصل 6 — اتصال کانتینرها به چند شبکه (Dual-Homed)

گاهی یک سرویس باید روی ۲ شبکه باشد:

  • backend (فقط برای API و DB)
  • monitoring (مثلاً برای Prometheus)

مثال:

services:
  api:
    networks:
      - backend
      - monitoring

این یعنی API در هر دو شبکه عضو است و می‌تواند به هر دو گروه دسترسی داشته باشد.

این الگو برای reverse-proxy ها خیلی رایج است (nginx → frontend + backend).

فصل 7 — External Networks

وقتی دو پروژه کاملاً جدا می‌خواهند با هم حرف بزنند:

docker network create sharednet

Project A:

networks:
  sharednet:
    external: true

Project B:

networks:
  sharednet:
    external: true

الان کانتینرهای دو پروژه در یک شبکه مشترک هستند.

فصل 8 — Network Modes (کم‌استفاده ولی مهم)

سه حالت مهم:

bridge (پیش‌فرض)

جداسازی کامل بین کانتینرها

کانتینرها فقط از طریق شبکه Docker با هم حرف می‌زنند.

host

کانتینر = خود سیستم

بدون ایزوله‌سازی

پورت‌ها به اشتراک گذاشته می‌شوند

معمولاً برای Redis یا Elasticsearch که latency حساس دارند.

none

کاملاً بدون شبکه

کاملاً ایزوله

تقریباً هیچ‌وقت استفاده نمی‌شود جز امنیت شدید.

فصل 9 — Debug شبکه

دستورات مهم:

docker network ls

نمایش همه شبکه‌ها

docker network inspect <network-name>

نمایش لیست کانتینرهای عضو، IP ها، alias ها

docker exec -it <container> sh
ping api

کانتینر به کانتینر دیگر ping می‌زند.

فصل 10 — معماری شبکه حرفه‌ای برای پروژه واقعی

یک الگوی واقعی:

frontend-network:
  nginx
  frontend

backend-network:
  nginx
  api
  auth-service
  cache

private-network:
  api
  auth-service
  postgres
  redis

monitor-network:
  prometheus
  grafana
  exporter

فواید:

  • frontend نمی‌تواند مستقیم DB را ببیند
  • monitoring به همه چیز دسترسی دارد
  • API چند کانال دارد
  • امنیت + معماری تمیز + توسعه‌پذیری

در 5 خط کل روح شبکه Docker این است:

  • هر سرویس یک hostname است.
  • فقط سرویس‌هایی که در یک شبکه مشترک هستند همدیگر را می‌بینند.
  • ports فقط برای ارتباط با خارج از Docker هستند.
  • alias اجازه می‌دهد چند سرویس با یک نام دیده شوند.
  • با شبکه‌های جداگانه می‌توان معماری تمیز، امن و قابل توسعه ساخت.