← Назад к вопросам
В чем разница между 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 для правильного взаимодействия сервисов!