Короткий ответ
По умолчанию docker-compose автоматически создаёт для проекта одну пользовательскую bridge-сеть и подключает к ней все сервисы, давая им DNS-резолв по имени сервиса "из коробки"; для изоляции отдельных сервисов друг от друга (например, чтобы фронтенд не мог напрямую обращаться к БД) нужно явно объявить несколько сетей в секции networks и назначить сервисам только нужные.
Как это работает подробнее
без явной секции networks compose создаёт сеть с именем вида PROJECT_default и добавляет туда все описанные сервисы — поведение по сути эквивалентно ручному docker network create плюс подключение каждого контейнера. Если же в compose-файле заданы несколько сетей и у каждого сервиса явно указано, к каким из них он подключён, сервисы, не состоящие в общей сети, не смогут резолвить и достигать друг друга.
Пример кода
services:
web:
image: myweb
networks: [frontend]
api:
image: myapi
networks: [frontend, backend]
db:
image: postgres:16
networks: [backend]
networks:
frontend:
backend:Что использовать на практике
- Практика. типичная схема — сеть
frontendдля веб-сервера и API, и отдельная сетьbackendдля API и БД, где веб-сервер вbackendне присутствует и физически не может напрямую обратиться к БД, даже зная её имя. Это дополнительный слой defense-in-depth на уровне сети, не заменяющий, но дополняющий авторизацию на уровне самой БД.
Подводные камни
- Риск. добавляют сервис во все сети "на всякий случай", из-за чего задуманная изоляция не работает; ожидают, что разделение на сети само по себе защищает от эксплуатации через уязвимость в сервисе, который всё же находится в обеих сетях (сеть снижает поверхность атаки, но не исключает риски внутри уже разрешённых соединений).