← Назад к вопросам

В чем разница между NAT и BRIDGE?

2.0 Middle🔥 21 комментариев
#DevOps и инфраструктура

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между NAT и BRIDGE в Docker сетях

Это вопрос про Docker сетевые драйверы (network drivers). Они определяют, как контейнеры взаимодействуют с хостом и друг с другом.

Быстрый ответ

NAT (Network Address Translation):
- Контейнер имеет свой IP внутри сети Docker
- Для доступа из внешнего мира нужно пробросить порты
- Изолированный (защищённый) подход

BRIDGE (мостовая сеть):
- Контейнер получает IP в подсети Docker
- Может взаимодействовать с другими контейнерами в сети
- Более интегрированный подход

1. NAT (Network Address Translation) — по умолчанию

Как работает NAT:

┌──────────────────────────────────────────────────────┐
│ HOST MACHINE (192.168.1.100)                         │
│                                                      │
│  ┌─────────────────────────────────────────────┐    │
│  │ Docker Daemon                               │    │
│  │  ┌────────────────────────────────────────┐ │    │
│  │  │ Container 1 (172.17.0.2)               │ │    │
│  │  │ :8000 (app)                            │ │    │
│  │  │                                        │ │    │
│  │  │ Порт пробрасываются через NAT:        │ │    │
│  │  │ Host 0.0.0.0:8080 → Container :8000   │ │    │
│  │  └────────────────────────────────────────┘ │    │
│  │                                             │    │
│  │  ┌────────────────────────────────────────┐ │    │
│  │  │ Container 2 (172.17.0.3)               │ │    │
│  │  │ :5432 (postgres)                       │ │    │
│  │  │                                        │ │    │
│  │  │ Порт пробрасываются через NAT:        │ │    │
│  │  │ Host 0.0.0.0:5432 → Container :5432   │ │    │
│  │  └────────────────────────────────────────┘ │    │
│  └─────────────────────────────────────────────┘    │
└──────────────────────────────────────────────────────┘

Пример с docker run:

# NAT по умолчанию
docker run -p 8000:8000 myapp
# -p = port mapping через NAT
# Host:8000 → Container:8000

Как настроить NAT явно:

# docker-compose.yml
version: '3.8'
services:
  app:
    image: myapp
    ports:
      - "8000:8000"  # NAT по умолчанию
    networks:
      - default  # Используется default bridge сеть (NAT)

Характеристики NAT:

  • ✅ Контейнеры изолированы от внешней сети
  • ✅ Контейнеры могут общаться между собой (в одной docker сети)
  • ❌ Контейнер не может получить IP хоста напрямую
  • ❌ Нужно пробросить каждый порт для доступа снаружи
  • ✅ По умолчанию, безопасно

2. BRIDGE — явная сетевая сеть

Как работает BRIDGE:

┌──────────────────────────────────────────────────────┐
│ HOST MACHINE (192.168.1.100)                         │
│                                                      │
│  ┌─────────────────────────────────────────────┐    │
│  │ Docker Daemon                               │    │
│  │  ┌──────────────────────────────────────┐   │    │
│  │  │ Bridge Network (app-net)             │   │    │
│  │  │ Subnet: 172.20.0.0/16                │   │    │
│  │  │                                      │   │    │
│  │  │  Container 1 (172.20.0.2)            │   │    │
│  │  │  hostname: app                       │   │    │
│  │  │  - может пингу Container 2           │   │    │
│  │  │  - может использовать имя 'postgres'│   │    │
│  │  │                                      │   │    │
│  │  │  Container 2 (172.20.0.3)            │   │    │
│  │  │  hostname: postgres                  │   │    │
│  │  │  - может пингу Container 1           │   │    │
│  │  │  - может использовать имя 'app'     │   │    │
│  │  │                                      │   │    │
│  │  │  Контейнеры видят друг друга по     │   │    │
│  │  │  имени и IP!                         │   │    │
│  │  └──────────────────────────────────────┘   │    │
│  └─────────────────────────────────────────────┘    │
└──────────────────────────────────────────────────────┘

Пример с docker compose и BRIDGE:

# docker-compose.yml
version: '3.8'
services:
  app:
    image: myapp
    networks:
      - app-net  # Явная bridge сеть
    environment:
      - DATABASE_HOST=postgres  # Можно использовать имя!
      - DATABASE_PORT=5432

  postgres:
    image: postgres:15
    networks:
      - app-net  # Та же bridge сеть

networks:
  app-net:  # Создаёт bridge сеть
    driver: bridge

Характеристики BRIDGE:

  • ✅ Контейнеры в одной bridge сети видят друг друга по имени
  • ✅ Встроенный DNS для service discovery
  • ✅ Изолирована от других bridge сетей
  • ✅ Контейнеры могут быть в разных bridge сетях
  • ❌ Немного медленнее, чем host (но разница минимальна)

3. Сравнение NAT vs BRIDGE

АспектNAT (default)BRIDGE
DNS между контейнерами❌ Нужно IP✅ Имена сервисов
Порты✅ Пробрасываются явно✅ Доступны в сети
Безопасность✅ Изолирована✅ Изолирована
Производительность✅ Хорошо✅ Хорошо
Service Discovery❌ Нету✅ Есть (встроенный DNS)
ИспользованиеПростые запускиProduction, docker-compose

4. Реальные примеры

Пример 1: ❌ НЕПРАВИЛЬНО (NAT)

# docker-compose.yml с NAT проблемой
version: '3.8'
services:
  app:
    image: myapp
    # Используется default bridge (NAT по сути)
    ports:
      - "8000:8000"
    environment:
      - DATABASE_HOST=localhost  # ❌ НЕПРАВИЛЬНО!
      - DATABASE_PORT=5432

  postgres:
    image: postgres:15
    ports:
      - "5432:5432"

# Проблема: в контейнере 'app' localhost = сам контейнер, не хост
# Запрос на localhost:5432 не может достигнуть PostgreSQL контейнера

Пример 2: ✅ ПРАВИЛЬНО (BRIDGE)

# docker-compose.yml с BRIDGE
version: '3.8'
services:
  app:
    image: myapp
    networks:
      - app-network  # Явная bridge сеть
    ports:
      - "8000:8000"
    environment:
      - DATABASE_HOST=postgres  # ✅ ПРАВИЛЬНО! Имя сервиса
      - DATABASE_PORT=5432

  postgres:
    image: postgres:15
    networks:
      - app-network  # Та же bridge сеть
    environment:
      - POSTGRES_PASSWORD=password

networks:
  app-network:
    driver: bridge  # Явная bridge сеть для service discovery

5. Практический код с примерами

# app.py (FastAPI)
import os
from sqlalchemy import create_engine

# С BRIDGE сетью это работает:
DATABASE_HOST = os.getenv("DATABASE_HOST", "postgres")
DATABASE_PORT = os.getenv("DATABASE_PORT", "5432")
DATABASE_NAME = os.getenv("DATABASE_NAME", "mydb")

# Connexion string
DATABASE_URL = f"postgresql://user:pass@{DATABASE_HOST}:{DATABASE_PORT}/{DATABASE_NAME}"
# С BRIDGE: DATABASE_HOST=postgres → 'postgres' резолвится в IP контейнера
# С NAT: DATABASE_HOST=postgres → будет ошибка (такого хоста нет)

engine = create_engine(DATABASE_URL)
# С NAT (неправильно):
docker run -p 8000:8000 -e DATABASE_HOST=localhost myapp
# ❌ localhost в контейнере = сам контейнер, не PostgreSQL

# С BRIDGE (правильно):
docker compose up
# ✅ postgres резолвится через DNS в IP контейнера PostgreSQL

6. Когда использовать каждый

Используй BRIDGE когда:

# ✅ ПРАВИЛЬНО: production-ready
version: '3.8'
services:
  api:
    build: .
    networks:
      - app-network
    environment:
      - DB_HOST=postgres  # Service discovery

  postgres:
    image: postgres:15
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

Используй NAT когда:

# ✅ ПРАВИЛЬНО: простой запуск одного контейнера
docker run -p 8000:8000 myapp
# Контейнер запускается в default bridge (NAT-ощущение)

# ✅ ПРАВИЛЬНО: разные контейнеры работают независимо
docker run -p 8000:8000 app
docker run -p 5432:5432 postgres
# Каждый проксируется через NAT отдельно

7. Host Network (третий вариант)

# ОЧЕНЬ редко используется, но существует
services:
  app:
    image: myapp
    network_mode: "host"  # Контейнер использует сеть хоста напрямую
    # Контейнер получает IP самого хоста
    # Порты не нужно пробрасывать
    # Очень быстро, но опасно (нет изоляции)

# ❌ Не рекомендуется для production

8. Диагностика сетей

# Просмотр сетей
docker network ls
# bridge              # Default bridge
# host                # Host network
# app-network         # Наша custom bridge

# Детали сети
docker network inspect app-network
# Увидишь контейнеры в сети и их IP

# Пинг между контейнерами (внутри bridge)
docker exec app ping postgres
# ✅ Работает! postgres резолвится в IP

# Проверка DNS
docker exec app nslookup postgres
# ✅ Вернёт IP контейнера postgres

Итоговый вывод

NAT (default bridge):

  • Простой, по умолчанию
  • Изолирует контейнеры
  • Нужно пробросить порты
  • Нет service discovery между контейнерами
  • Хорошо для одного контейнера

BRIDGE (custom bridge):

  • Явная конфигурация
  • Встроенный DNS для имён сервисов
  • Контейнеры в одной сети видят друг друга по имени
  • Идеально для docker-compose с несколькими сервисами
  • Standard для production

Правило большого пальца:

  • Используй BRIDGE в docker-compose для service discovery
  • Используй NAT для простых одиночных контейнеров

В современной разработке (docker-compose) практически всегда нужен BRIDGE для правильного взаимодействия сервисов!