Контейнеры изолированы, но часто должны взаимодействовать друг с другом и с внешним миром. Docker решает это через сетевые драйверы.
Сетевые драйверы
Docker поддерживает несколько типов сетей:
| Драйвер | Описание |
|---|---|
bridge |
Виртуальная сеть на хосте. По умолчанию для всех контейнеров |
host |
Контейнер использует сетевой стек хоста напрямую |
none |
Нет сети. Полная изоляция |
overlay |
Для Swarm: сеть поверх нескольких хостов |
docker network ls # список сетей
docker network inspect bridge # детали сети
docker network create my-network # создать сеть
docker network rm my-network # удалить сеть
Default bridge: контейнеры общаются по IP
По умолчанию каждый контейнер подключается к сети bridge. Контейнеры видят друг друга только по IP-адресу.
# Запустить два контейнера
docker run -d --name app1 alpine sleep infinity
docker run -d --name app2 alpine sleep infinity
# Узнать IP первого
docker inspect app1 | grep IPAddress
# → 172.17.0.2
# Из app2 пинговать app1 по IP
docker exec app2 ping 172.17.0.2
Проблема: IP меняется при перезапуске. Решение — user-defined network.
User-defined network: DNS по имени контейнера
В пользовательской сети Docker автоматически регистрирует DNS-записи по имени контейнера. Контейнеры обращаются друг к другу по имени.
# Создать сеть
docker network create my-app-net
# Запустить контейнеры в этой сети
docker run -d --name postgres --network my-app-net postgres:15
docker run -d --name web --network my-app-net my-web-app
# Из web можно обратиться к postgres по имени:
# postgresql://postgres:5432/db
Имя контейнера — надёжный адрес. DNS работает автоматически.
Как Docker Compose создаёт сеть
Docker Compose автоматически создаёт отдельную сеть для каждого проекта. Все сервисы в docker-compose.yml подключаются к ней и видят друг друга по имени сервиса.
services:
web:
build: .
# Может обращаться к "db" и "redis" по имени
db:
image: postgres:15
redis:
image: redis:7
Сеть называется <папка-проекта>_default. Никакой дополнительной настройки не нужно.
Для изоляции сервисов можно объявить несколько сетей явно:
services:
web:
networks:
- frontend
- backend
db:
networks:
- backend # db недоступна снаружи backend
networks:
frontend:
backend:
Проброс портов: -p HOST:CONTAINER
Контейнер по умолчанию недоступен снаружи. Флаг -p пробрасывает порт хоста в порт контейнера.
# Синтаксис: -p ХОСТ:КОНТЕЙНЕР
docker run -p 8080:80 nginx # localhost:8080 → контейнер:80
docker run -p 127.0.0.1:8080:80 nginx # только с локалхоста
docker run -p 5432:5432 postgres # postgres доступен с хоста
# Несколько портов
docker run -p 80:80 -p 443:443 nginx
# Случайный порт хоста
docker run -p 80 nginx # Docker сам выберет порт
docker port <container> # узнать какой порт назначен
В docker-compose.yml:
ports:
- "8080:80" # хост:контейнер
- "127.0.0.1:5432:5432" # только localhost
Пример: nginx + app + postgres
Полный стек с разными сетями для изоляции:
version: "3.8"
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
networks:
- frontend
depends_on:
- app
app:
build: .
environment:
DATABASE_URL: postgresql://user:pass@postgres:5432/mydb
networks:
- frontend
- backend
depends_on:
- postgres
postgres:
image: postgres:15
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- pgdata:/var/lib/postgresql/data
networks:
- backend # postgres не виден из nginx
volumes:
pgdata:
networks:
frontend:
backend:
Конфигурация nginx для проксирования на app:
server {
listen 80;
location / {
proxy_pass http://app:8000;
}
}
nginx обращается к app по имени сервиса. app обращается к postgres по имени сервиса. postgres изолирован в сети backend и недоступен из интернета.
Полезные команды для диагностики
# Посмотреть все сети
docker network ls
# Что подключено к сети
docker network inspect my-app-net
# IP-адреса контейнера
docker inspect web | grep -A 20 '"Networks"'
# Проверить связь между контейнерами
docker exec app ping db
docker exec app curl http://nginx/health
💬 Комментарии (0)
Комментариев пока нет
Станьте первым, кто поделится мнением об этой статье!