Урок по треку Docker и Kubernetes 7 мин

Сети и тома Docker за 7 минут

bridge, host, none, публикация портов, DNS между контейнерами, volumes, bind mounts и tmpfs.

Два вопроса, на которых спотыкаются чаще всего: «почему контейнер не видит базу» и «куда делись данные после пересоздания контейнера». Оба про то, как Docker устраивает сеть и хранение.

Сетевые драйверы

  • bridge (по умолчанию): у контейнера свой network namespace, виртуальная пара veth соединяет его с мостом на хосте (docker0 для сети по умолчанию). Наружу контейнер выходит через NAT (masquerade).
  • host: контейнер использует сеть хоста напрямую, без изоляции и без публикации портов. Быстро, но порты конфликтуют с хостом. Полноценно работает только на Linux.
  • none: только loopback, сети нет.
  • overlay: сеть между несколькими хостами (Swarm).
  • macvlan/ipvlan: контейнер получает адрес в физической сети.

Пользовательская сеть и DNS

docker network create app-net
docker run -d --name db  --network app-net postgres:16
docker run -d --name api --network app-net -e DB_HOST=db my/api

В пользовательской bridge-сети работает встроенный DNS Docker (адрес 127.0.0.11 внутри контейнера): контейнеры находят друг друга по имени и по алиасам. В сети по умолчанию bridge такого DNS нет, только IP. Отсюда классическая ошибка: два контейнера, запущенных без --network, не видят друг друга по имени.

IP контейнера меняется при пересоздании, поэтому ходить надо по имени, а не по IP.

Публикация портов

docker run -p 8080:80 nginx            # хост 0.0.0.0:8080 → контейнер :80
docker run -p 127.0.0.1:5432:5432 db   # только с localhost хоста
docker run -P nginx                    # все EXPOSE-порты на случайные порты хоста
docker port <container>

Docker реализует публикацию правилами iptables (DNAT в таблице nat). Важное следствие: опубликованный порт обходит правила ufw, потому что пакеты идут через цепочку FORWARD и правила Docker, а не через INPUT, которую настраивает ufw. Базу, опубликованную как -p 5432:5432, будет видно из интернета, даже если ufw «закрыт». Для внутренних сервисов либо не публикуют порт вовсе (контейнеры общаются по внутренней сети), либо привязывают к 127.0.0.1.

Ещё ловушка: приложение внутри контейнера слушает 127.0.0.1. Тогда публикация не поможет: трафик приходит на интерфейс контейнера eth0. Внутри контейнера надо слушать 0.0.0.0.

Из контейнера к сервису на хосте: host.docker.internal в Docker Desktop, на Linux добавляют --add-host=host.docker.internal:host-gateway.

Хранение данных

Записываемый слой контейнера живёт, пока жив контейнер, и медленнее обычной ФС. Для данных три механизма:

Где лежитДля чего
volumeуправляет Docker (/var/lib/docker/volumes/...)данные баз и сервисов
bind mountлюбой путь хостаконфиги, код в разработке
tmpfsпамятьвременное и секретное, не пишем на диск
docker volume create pgdata
docker run -v pgdata:/var/lib/postgresql/data postgres:16
docker run -v "$PWD/nginx.conf:/etc/nginx/nginx.conf:ro" nginx
docker run --mount type=tmpfs,target=/tmp app
docker volume ls; docker volume inspect pgdata

Синтаксис --mount длиннее, но явный; -v короче. Если в -v указан путь (начинается с / или ./), это bind mount, если имя, то том.

Особенности:

  • Пустой именованный том при первом подключении заполняется содержимым образа по этому пути. Bind mount просто перекрывает каталог образа содержимым хоста, даже пустым.
  • Тома переживают docker rm. Удаляются явно: docker volume rm, docker rm -v для анонимных, docker volume prune.
  • Права: процесс в контейнере работает со своим UID, и на bind mount он может не иметь доступа к файлам хоста (или наоборот, создавать файлы root на хосте).
  • Флаг :ro монтирует только для чтения.

Бэкап тома

docker run --rm -v pgdata:/data -v "$PWD":/backup alpine \
  tar czf /backup/pgdata.tgz -C /data .

Для баз правильнее логический дамп (pg_dump) или средства самой СУБД: копия файлов работающей базы может оказаться неконсистентной.

Частые ошибки

  • Контейнеры в сети по умолчанию ищут друг друга по имени.
  • Приложение слушает 127.0.0.1 внутри контейнера.
  • -p 5432:5432 для базы на публичном сервере в надежде на ufw.
  • Данные базы без тома: пропадают при пересоздании контейнера.
  • Bind mount пустого каталога поверх каталога с данными образа.

Что спросят на собесе

  • Какие сетевые драйверы есть и чем bridge отличается от host.
  • Как контейнеры находят друг друга по имени.
  • Volume против bind mount, где что использовать.
  • Почему опубликованный порт виден снаружи несмотря на ufw.
  • Что будет с данными при docker rm и при docker compose down -v.

Закрепите за 5 минут

После урока в тренажёре 3-5 проверочных вопросов, дальше модуль уходит в повторения.