Что происходит по умолчанию:
При установке Docker создает три сети, посмотреть их можно так:
Код: Выделить всё
docker network lsСеть host убирает изоляцию: контейнер использует сетевой стек хоста напрямую (полноценно это работает только на Linux). Сеть none отключает сеть совсем. Обе нужны редко, для типовых задач хватает bridge-сетей.
Пользовательские сети:
Правильный путь: создать свою сеть и запустить контейнеры в ней.
Код: Выделить всё
docker network create app-net
docker run -d --name pg --network app-net \
-e POSTGRES_PASSWORD=secret postgres:16
docker run -d --name api --network app-net \
-p 8080:8080 my-api:1.0Код: Выделить всё
postgres://postgres:secret@pg:5432/postgresКод: Выделить всё
docker exec -it api sh
# внутри контейнера (если образ на alpine)
nc -z pg 5432 && echo "база доступна"Контейнер можно подключать к сетям и на лету:
Код: Выделить всё
docker network inspect app-net
docker network connect app-net redis
docker network disconnect app-net redisТипичные грабли:
Первое и главное: localhost внутри контейнера указывает на сам контейнер, а не на вашу машину. Если приложение в контейнере пытается достучаться до postgres://localhost:5432, а Postgres крутится в соседнем контейнере или на хосте, ничего не выйдет. Для соседнего контейнера используйте его имя. Для хоста на Docker Desktop (Mac и Windows) есть специальное имя host.docker.internal, на Linux его нужно добавить вручную флагом --add-host=host.docker.internal:host-gateway.
Второе: при общении контейнеров используется внутренний порт, а не опубликованный. Если вы запустили базу с -p 55432:5432, то с хоста подключаетесь к localhost:55432, а из соседнего контейнера все равно к pg:5432.
Третье: имена резолвятся только в пользовательских сетях. Запустили два контейнера без --network и удивляетесь, почему обращение по имени не работает. Потому что они в дефолтном bridge, там DNS по именам контейнеров нет.
Что усвоили:
Контейнеры связываются через сети. Создавайте свои bridge-сети и обращайтесь к соседям по имени контейнера, а порты публикуйте только там, где нужен доступ снаружи. В главе 8 Docker Compose будет создавать такие сети за вас автоматически, и вы узнаете в его конфиге все, что мы сейчас делали руками. А следующая глава про переменные окружения: пароль от базы, который мы прописали прямо в команде запуска, так оставлять нельзя.