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

Как работает Docker сеть?

2.0 Middle🔥 201 комментариев
#Docker, Kubernetes и DevOps

Комментарии (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Локальная разработкаСредняяНет
hostHigh performanceНетНет (конфликты портов)
overlayDocker Swarm/K8sХорошаяДа
macvlanPhysical сетьОтличнаяСпециальные случаи

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

  1. Всегда используй именованные сети для многоконтейнерных приложений
  2. docker-compose для локальной разработки (автоматизирует сеть)
  3. Не используй --link (deprecated)
  4. Проверяй доступность перед production:
    docker exec app curl http://db:5432
    
  5. Health checks в docker-compose:
    healthcheck:
      test: ["CMD", "pg_isready", "-h", "localhost"]
      interval: 10s
    
  6. Используй overlay для Docker Swarm/K8s
  7. Документируй env переменные для подключения между контейнерами
Как работает Docker сеть? | PrepBro