За замовчуванням Compose підключає всі сервіси проєкту до однієї мережі default. Кожен контейнер бачить кожен: зворотний проксі може під'єднатися до бази, а сервіс обробки зображень - до Redis із сесіями.
Якщо будь-який сервіс зламано (вразливість у бібліотеці обробки файлів, сторонній образ), зловмисник отримує мережевий доступ до всіх інших.
Сегментація - кілька мереж за принципом «хто з ким має говорити»:
services:
proxy:
image: caddy
ports: ["443:443"]
networks: [edge]
app:
image: myapp
networks: [edge, data]
worker:
image: myapp
command: php artisan queue:work
networks: [data, egress]
postgres:
image: postgres:18
networks: [data]
redis:
image: redis:8
networks: [data]
networks:
edge:
data:
internal: true # без маршруту в інтернет
egress: # окрема мережа з виходом назовні
Що це дає:
- проксі бачить лише застосунок - не базу й не Redis;
- база й Redis у мережі
internal: true- не можуть самі звертатися в інтернет (зламана база не завантажить шкідливий код і не відправить дані назовні); - воркер має вихід в інтернет для сторонніх API, але не стоїть «на краю» - до нього не звертаються ззовні.
Додаткові прийоми:
- без
portsдля всього, крім точки входу; - окремі облікові записи бази для застосунку й воркерів з мінімальними правами - мережа обмежує, хто може під'єднатися, права - що можна зробити після під'єднання;
- аліаси мереж - сервіс може мати різні імена в різних мережах.
Обмеження: мережі Docker - це сегментація на рівні з'єднань (L3/L4). Вони не замінюють автентифікацію між сервісами: Redis і база мають паролі навіть у внутрішній мережі. Для політик на рівні окремих потоків і шифрування між сервісами - оркестратори з мережевими політиками (Kubernetes NetworkPolicy) чи service mesh.
Перевірка: docker compose exec proxy nc -zv postgres 5432 має не з'єднатися - сегментація працює лише тоді, коли її перевірили.