core code helper

Мережі та томи в Docker: як контейнери бачать одне одного і де живуть дані

Bridge, host і внутрішні мережі, публікація портів, іменовані томи проти bind-mount і чому дані не повинні жити всередині контейнера.

0 імпортували Імпортувати собі

Контейнер — це ізольований процес: своя файлова система, свій мережевий стек. Два питання виникають у всіх, хто запускає щось складніше за «hello world»: як контейнерам спілкуватися і де зберігати дані, щоб вони не зникли.

Типи мереж

Драйвер Що це Коли використовувати
bridge (за замовчуванням) Віртуальна мережа на хості з NAT назовні Більшість застосунків на одному хості
Користувацька bridge Те саме + DNS за іменами контейнерів Завжди замість стандартної bridge
host Контейнер використовує мережу хоста напряму Максимальна мережева продуктивність, Linux
none Без мережі Пакетні задачі, що не потребують мережі
overlay Мережа між кількома хостами Swarm, кластери

Чому стандартна bridge — погана ідея

У стандартній мережі bridge контейнери не знаходять одне одного за іменами. У користувацькій — знаходять через вбудований DNS:

docker network create app-net

docker run -d --name db --network app-net \
  -e POSTGRES_PASSWORD=secret postgres:17-alpine

docker run --rm --network app-net postgres:17-alpine \
  pg_isready -h db -U postgres
# db:5432 - accepting connections

Docker Compose створює окрему мережу для кожного проєкту автоматично — тому там імена сервісів працюють «самі».

Ізоляція: внутрішні мережі

База даних не повинна бути доступна ззовні — і бажано, щоб вона сама не ходила в інтернет. Для цього є прапорець internal:

services:
  app:
    networks: [frontend, backend]
  db:
    networks: [backend]

networks:
  frontend: {}
  backend:
    internal: true   # без виходу назовні і без доступу ззовні

Застосунок бачить і інтернет, і базу; база — лише застосунок.

Публікація портів: обережно з 0.0.0.0

docker run -p 5432:5432 postgres     # відкрито на ВСІХ інтерфейсах хоста
docker run -p 127.0.0.1:5432:5432 postgres   # лише локально
Обережно

Docker сам додає правила в iptables для опублікованих портів і може обійти налаштування фаєрволу на кшталт UFW. Опублікований -p 5432:5432 на сервері з публічною IP-адресою — відкрита в інтернет база, навіть якщо UFW «все блокує». Публікуйте порти лише на 127.0.0.1 або взагалі не публікуйте, а ходіть через реверс-проксі.

Де живуть дані

Файлова система контейнера тимчасова: видалили контейнер — зникли дані. Для всього, що має пережити перезапуск, є три варіанти:

Тип Приклад Особливості
Іменований том -v pgdata:/var/lib/postgresql/data Керує Docker, переносний, найкращий для баз
Bind-mount -v ./config:/etc/app:ro Папка з хоста; зручно для конфігів і коду в розробці
tmpfs --tmpfs /tmp У пам'яті, зникає після зупинки; для тимчасових і чутливих файлів
docker volume ls
docker volume inspect pgdata          # де фізично лежать дані
docker volume rm pgdata               # видалити (лише якщо не використовується)
docker system df -v                   # скільки місця займають томи
Порада

Монтуйте конфіги з прапорцем :ro (лише читання). Якщо застосунок зламають, він не зможе переписати власну конфігурацію.

Права на файлах у bind-mount

Часта проблема: контейнер працює від користувача з UID 1000, а папка на хості належить root — і застосунок не може писати.

# Подивитися, від кого працює процес у контейнері
docker exec app id
# uid=1000(node) gid=1000(node)

# Віддати папку цьому UID на хості
sudo chown -R 1000:1000 ./data

Іменовані томи цієї проблеми зазвичай не мають: Docker копіює права з образу при першому монтуванні.

Бекап тому

docker run --rm \
  -v pgdata:/data:ro \
  -v "$(pwd)":/backup \
  alpine tar czf /backup/pgdata-$(date +%F).tar.gz -C /data .
Увага

Копіювати файли працюючої бази даних — ризиковано: можна отримати неконсистентну копію. Для PostgreSQL використовуйте pg_dump або pg_basebackup, а файловий бекап робіть при зупиненому контейнері.

Ви запустили nginx з -p 8080:80, а UFW на сервері дозволяє лише 22 і 443. Чи доступний 8080 з інтернету?

Так, найімовірніше доступний. Docker додає власні правила в iptables (ланцюжок DOCKER), які обробляються раніше за правила UFW. Щоб порт був недоступний ззовні, публікуйте його як 127.0.0.1:8080:80 або налаштуйте правила в ланцюжку DOCKER-USER.

Збережіть статтю собі

Увійдіть, щоб імпортувати її у власні нотатки, відмічати вивчене, ставити лайки й питати спільноту. Реєстрація безкоштовна: вхід через Google займає кілька секунд.

Увійти через Google Інші способи входу