Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Как работает Docker сеть
Основные концепции
Docker сеть обеспечивает коммуникацию между контейнерами и хостом. Это виртуальная сеть, изолированная от остального трафика.
1. Bridge Network (стандартная сеть)
По умолчанию
# При запуске контейнера по умолчанию используется bridge сеть
docker run -d --name web nginx
# Контейнер получает виртуальный IP (обычно 172.17.0.x)
Архитектура Bridge
┌─────────────────────────────────────────────┐
│ Host Machine (192.168.1.100) │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ docker0 (виртуальный интерфейс) │ │
│ │ IP: 172.17.0.1 │ │
│ └──────────────────────────────────────┘ │
│ ▲ ▲ │
│ │ │ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Container1 │ │ Container2 │ │
│ │ 172.17.0.2 │ │ 172.17.0.3 │ │
│ │ (nginx) │ │ (mysql) │ │
│ └─────────────────┘ └─────────────────┘ │
│ veth1 veth2 │
└─────────────────────────────────────────────┘
Коммуникация в Bridge сети
# Контейнеры видят друг друга по имени (DNS)
docker run -d --name web nginx
docker run -d --name api --link web myapi
# Из api контейнера:
ping web # Работает! (172.17.0.2)
curl http://web:80 # Работает!
Проблема: Стандартная bridge сеть
# ❌ Контейнеры НЕ видят друг друга по имени по умолчанию
docker run -d --name db postgres
docker run -d --name app myapp
# Из app контейнера:
ping db # НЕ работает (нет DNS)
Решение: Пользовательская bridge сеть
# 1. Создаём собственную сеть
docker network create myapp-network
# 2. Запускаем контейнеры в этой сети
docker run -d --name db --network myapp-network postgres
docker run -d --name app --network myapp-network myapp
# 3. Теперь они видят друг друга по имени
# Из app контейнера:
pg_isready -h db -p 5432 # Работает!
2. Host Network
# Контейнер использует сетевой интерфейс хоста
docker run --network host nginx
# Контейнер видит IP хоста (192.168.1.100)
ifconfig # Показывает интерфейсы хоста
Плюсы
- Максимальная производительность (нет NAT overhead)
- Контейнер напрямую видит трафик хоста
Минусы
- Конфликты портов (если nginx занимает :80, другой контейнер не может)
- Нет изоляции
3. Overlay Network (Docker Swarm)
# Для микросервисов на нескольких машинах
docker swarm init
# Создаём overlay сеть
docker network create --driver overlay myapp-net
# Сервисы в разных контейнерах видят друг друга
Архитектура
Host 1 (192.168.1.100) Host 2 (192.168.1.101)
┌──────────────────┐ ┌──────────────────┐
│ Container1 │ │ Container2 │
│ 10.0.0.2 │◄────────►│ 10.0.0.3 │
└──────────────────┘ Overlay │─────────────────│
vxlan Tunnel │ │
└──────────────────┘
4. Port Mapping (публикация портов)
# Пробрасываем порт контейнера на хост
docker run -p 8080:80 nginx
# ▲ ▲
# хост порт порт контейнера
# Доступ:
http://localhost:8080 # Перенаправляется на контейнер:80
Как работает
Client (192.168.1.200) ──► Host:8080 (192.168.1.100)
│
▼ NAT
Container:80 (172.17.0.2)
Множественные порты
docker run -p 8080:80 -p 3306:3306 --name myapp myapp
# localhost:8080 → контейнер:80 (nginx)
# localhost:3306 → контейнер:3306 (mysql)
5. Container Networking: Docker Compose
version: '3.8'
services:
web:
image: nginx
ports:
- "8080:80"
networks:
- app-network
db:
image: postgres
networks:
- app-network
environment:
POSTGRES_PASSWORD: password
networks:
app-network:
driver: bridge
Автоматическое разрешение имён
docker-compose up
# Из web контейнера:
curl http://db:5432 # Работает! (db.app-network → 172.17.0.3)
6. DNS в Docker
Embedded DNS Server
# Docker встроенный DNS слушает на 127.0.0.11:53
# Из контейнера в bridge сети:
# ping web
# 1. Запрос: 127.0.0.11:53 (Docker DNS)
# 2. Ответ: 172.17.0.2 (IP контейнера web)
# 3. ARP request: 172.17.0.2
# 4. Пакеты отправляются на контейнер
7. Практический пример: Java Spring Boot + PostgreSQL
docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:14
container_name: mydb
ports:
- "5432:5432"
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
networks:
- app-network
app:
build:
context: .
dockerfile: Dockerfile
container_name: myapp
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/mydb
SPRING_DATASOURCE_USERNAME: user
SPRING_DATASOURCE_PASSWORD: password
depends_on:
- postgres
networks:
- app-network
networks:
app-network:
driver: bridge
Как работает
1. Docker создаёт сеть app-network
2. Стартует postgres контейнер
- DNS: postgres → 172.17.0.2
3. Стартует app контейнер
- Коннектится к SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/mydb
- DNS разрешает postgres → 172.17.0.2
- TCP соединение на 172.17.0.2:5432
- Успешно коннектится
8. Network Drivers: Сравнение
| Driver | Использование | Изоляция | Production |
|---|---|---|---|
| bridge | Локальная разработка | Средняя | Нет |
| host | High performance | Нет | Нет (конфликты портов) |
| overlay | Docker Swarm/K8s | Хорошая | Да |
| macvlan | Physical сеть | Отличная | Специальные случаи |
9. Диагностика сети
# Какие контейнеры в сети
docker network inspect myapp-network
# Output:
[
{
"Name": "myapp-network",
"Containers": {
"abc123...": {
"Name": "web",
"IPv4Address": "172.17.0.2/16"
},
"def456...": {
"Name": "db",
"IPv4Address": "172.17.0.3/16"
}
}
}
]
# Из контейнера: есть ли доступ?
docker exec web ping db
docker exec web curl http://db:5432
# Логи контейнера
docker logs web
10. Common Issues & Solutions
Проблема 1: "Контейнер не видит другой контейнер"
# ❌ Без именованной сети
docker run -d --name db postgres
docker run --name app myapp # ping db не работает
# ✅ С именованной сетью
docker network create mynet
docker run -d --name db --network mynet postgres
docker run --name app --network mynet myapp # ping db работает
Проблема 2: "Порт уже занят"
# ❌ Конфликт на хосте
docker run -p 8080:80 nginx
docker run -p 8080:80 httpd # Ошибка!
# ✅ Используй другой порт на хосте
docker run -p 8081:80 httpd # ОК
Проблема 3: "localhost не работает из контейнера"
# ❌ Неправильно
docker run --name app myapp
# В контейнере:
curl http://localhost:5432 # Не найдёт (другой namespace)
# ✅ Правильно
docker run --network host myapp # ИЛИ
curl http://db:5432 # Использовать имя контейнера
My Best Practices
- Всегда используй именованные сети для многоконтейнерных приложений
- docker-compose для локальной разработки (автоматизирует сеть)
- Не используй --link (deprecated)
- Проверяй доступность перед production:
docker exec app curl http://db:5432 - Health checks в docker-compose:
healthcheck: test: ["CMD", "pg_isready", "-h", "localhost"] interval: 10s - Используй overlay для Docker Swarm/K8s
- Документируй env переменные для подключения между контейнерами