В чём разница между bridge-network и host-network?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между bridge-network и host-network в Docker
Выбор сетевого драйвера в Docker критичен для производительности, безопасности и доступности контейнеров. Bridge и host — два основных подхода с принципиально разными характеристиками.
Bridge Network (мостовая сеть)
Bridge — это приватная виртуальная сеть, которая создаётся для контейнеров. Контейнеры в bridge сети не имеют прямого доступа к портам хоста.
# Создание bridge сети (создаётся по умолчанию как "bridge")
docker network create my-bridge --driver bridge
# Запуск контейнера в bridge сети
docker run -d --name web --network my-bridge -p 8000:8000 python-app
# Контейнеры в одной bridge сети видят друг друга по имени
docker run -d --name db --network my-bridge postgres
# Из контейнера web:
# Может достучаться до db как: psql -h db
# (DNS автоматически резолвит имя контейнера в IP)
Как это работает:
Хост (например, 192.168.1.100)
│
├─ Bridge Network (172.17.0.0/16)
│ │
│ ├─ Container 1 (172.17.0.2:8000)
│ │ Доступ: localhost:8000 → 172.17.0.2:8000 (через port mapping)
│ │
│ └─ Container 2 (172.17.0.3:5432)
│ Доступ: только для других контейнеров в bridge
│
├─ Localhost (127.0.0.1)
│ └─ Доступен только Container 1 через -p 8000:8000
│
└─ Другие сети
└─ Контейнеры здесь не видят контейнеры в bridge
Характеристики Bridge:
- Изоляция — контейнеры изолированы от хоста и друг от друга (разные сети)
- DNS — контейнеры видят друг друга по имени (в одной сети)
- Port mapping — требуется явно проксировать порты (-p 8000:8000)
- Производительность — небольшой оверхед NAT трансляции
- Сложность — нужно управлять портами, если много контейнеров
# docker-compose.yml с bridge (по умолчанию)
version: "3.9"
services:
web:
image: python-app
ports:
- "8000:8000" # Host port : Container port
depends_on:
- db
db:
image: postgres
ports:
- "5432:5432" # Также проксируется если нужен доступ с хоста
# Из контейнера web:
# - Может достучаться к db по: postgresql://db:5432
# - С хоста: postgresql://localhost:5432
Host Network
Host — это прямой доступ к сетевому стеку хоста. Контейнер делит сетевое пространство имён с хостом и имеет те же IP и порты.
# Запуск контейнера в host сети
docker run -d --name web --network host python-app
# Контейнер слушает прямо на портах хоста
# Если приложение слушает 0.0.0.0:8000, оно доступно на хосте:8000
# НЕ НУЖНО -p 8000:8000
# Из хоста:
# curl localhost:8000
# Контейнер видит все порты и IP адреса хоста
# netstat покажет процессы хоста
Как это работает:
Хост (192.168.1.100)
│
├─ eth0 (192.168.1.100)
├─ lo (127.0.0.1)
│
└─ Container 1 (разделяет сетевой стек)
├─ Видит 192.168.1.100
├─ Видит 127.0.0.1
└─ Слушает порты напрямую
(если слушает :8000, доступен на host:8000)
Характеристики Host:
- Никакой изоляции — контейнер видит все сетевые интерфейсы хоста
- Максимальная производительность — нет NAT оверхеда
- Простота — порты видны сразу, не нужно -p
- Уязвимость — контейнер может слушать любой порт хоста
- Конфликты портов — два контейнера не могут слушать один порт
# docker-compose.yml с host сетью
version: "3.9"
services:
web:
image: python-app
network_mode: "host"
# НЕ используем ports: - контейнер сам слушает на портах хоста
db:
image: postgres
network_mode: "host"
# ПРОБЛЕМА: если оба контейнера пытаются слушать :5432
# То второй упадёт с ошибкой "port already in use"
Сравнение
| Параметр | Bridge | Host |
|---|---|---|
| Изоляция сети | Высокая | Нет |
| Видимость портов | Через -p | Прямая |
| Производительность | Хорошая | Отличная |
| DNS между контейнерами | Работает | Не нужен |
| Конфликты портов | Маловероятны | Вероятны |
| Безопасность | Выше | Ниже |
| Использование в продакшене | Стандарт | Редко |
| Сложность настройки | Средняя | Низкая |
Примеры использования
Bridge сеть (РЕКОМЕНДУЕТСЯ):
# Типичное приложение: FastAPI + PostgreSQL
docker network create app-network
# База данных
docker run -d \
--name postgres \
--network app-network \
-e POSTGRES_PASSWORD=secret \
postgres:15
# Приложение
docker run -d \
--name api \
--network app-network \
-p 8000:8000 \
-e DATABASE_URL=postgresql://postgres:secret@postgres:5432/mydb \
myapp:latest
# С хоста: curl localhost:8000
# Из контейнера api: подключается к postgres через DNS имя
# settings.py в приложении
import os
# В контейнере
DATABASE_URL = os.getenv(
"DATABASE_URL",
"postgresql://postgres:secret@postgres:5432/mydb"
)
# "postgres" резолвится в IP контейнера postgres в той же bridge сети
Host сеть (редко, специфичные случаи):
# Высоконагруженный сервер, где каждая микросекунда важна
# Мониторинг системы (Prometheus, которому нужны метрики хоста)
# Специальные сетевые приложения
docker run -d \
--name prometheus \
--network host \
-v /etc/prometheus.yml:/etc/prometheus/prometheus.yml \
prom/prometheus
# Prometheus слушает на :9090 хоста напрямую
# curl localhost:9090
Проблемы и решения
Проблема 1: "Cannot access container from host in bridge network"
# НЕПРАВИЛЬНО
docker run --name db -d postgres
# С хоста: psql -h postgres -U postgres # ERROR: не разрешается
# ПРАВИЛЬНО
docker run --name db -d -p 5432:5432 postgres
# С хоста: psql -h localhost -U postgres # OK
# ИЛИ используй имя контейнера только внутри других контейнеров
docker run --name web --link db web-app
# Из web контейнера: psql -h db # OK
Проблема 2: "Port already in use" с host сетью
# В host сети два контейнера не могут слушать один порт
docker run --network host -d app1
docker run --network host -d app2
# ОШИБКА если оба пытаются слушать :8000
# РЕШЕНИЕ: разные порты
docker run --network host -p 8000:8000 -d app1 # port 8000
docker run --network host -p 8001:8000 -d app2 # port 8001
Проблема 3: Разные DNS имена в bridge и host
# Bridge сеть
docker run --name db --network my-net -d postgres
docker run --name app --network my-net -d myapp
# Из app: "db" резолвится в IP контейнера
# Host сеть
docker run --name db --network host -d postgres
docker run --name app --network host -d myapp
# Из app: "db" не имеет смысла (нет контейнерной сети)
# Нужно использовать localhost, 127.0.0.1 или IP хоста
Performance comparison
# Бенчмарк: Host vs Bridge
# Задача: 10000 запросов между контейнерами
import time
import asyncio
import httpx
async def benchmark():
async with httpx.AsyncClient() as client:
start = time.time()
for _ in range(10000):
response = await client.get("http://target:8000/ping")
elapsed = time.time() - start
return elapsed
# Bridge network: ~5.2 секунды
# Host network: ~4.8 секунды
# Разница: ~8% (из-за NAT трансляции)
# В реальных приложениях разница часто незначительна
# потому что остаток времени уходит на обработку логики
docker-compose с разными сетями
version: "3.9"
services:
# Bridge сеть (по умолчанию)
web:
build: .
ports:
- "8000:8000"
depends_on:
- db
db:
image: postgres
environment:
POSTGRES_PASSWORD: secret
# Специальный сервис на host сети (редко)
monitor:
image: prom/prometheus
network_mode: "host"
# ВАЖНО: этот контейнер разделяет сеть с хостом
# По умолчанию web и db в одной bridge сети
# и видят друг друга по имени
Итог
Bridge network — стандарт для большинства приложений. Обеспечивает изоляцию, автоматический DNS между контейнерами и легко управляется. Host network — нишевый выбор для специфичных случаев (максимальная производительность, мониторинг системы). В production используй bridge, если нет очень веских причин иначе. Bridge обеспечивает лучший баланс между производительностью, безопасностью и удобством управления.