В сети Compose сервисы находят друг друга по имени. localhost внутри контейнера — это не Postgres на ноутбуке. Том переживает удаление контейнера. Healthcheck говорит, готов ли сервис, а не «процесс просто стартовал».
Контейнеры и оркестрация docker собеседование
Docker Compose поднимает несколько контейнеров вместе: общая сеть, DNS по имени сервиса, тома, порядок старта. Это удобно локально. Это не Kubernetes.
Многие прод-ошибки видны уже здесь: не тот localhost, потеря данных, api стартовал раньше базы.
Сети и localhost
Compose создаёт свою сеть. Имя сервиса в YAML становится DNS-именем. Контейнер api ходит к базе как postgres:5432.
Внутри контейнера localhost — сам этот контейнер. Не ноутбук. Не соседний сервис. Порт 5432 на хосте сюда не «просвечивает».
Секция ports: нужна вам на машине: браузер, psql, IDE. Внутри сети Compose она не обязательна. Сервисы ходят друг к другу по имени.
Пример. На ноутбуке открыт localhost:5432 — вы подключаетесь к Postgres с хоста. Тот же адрес из контейнера api попадёт в сам api. Базы там нет. Нужен хост postgres.
services:
postgres:
image: postgres:16
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 5s
retries: 10
api:
build: .
environment:
DATABASE_URL: postgres://app@postgres:5432/app
depends_on:
postgres:
condition: service_healthy
volumes:
pgdata:
API резолвит postgres по DNS сети. Старт ждёт healthcheck. Данные живут в named volume.
Тома
Контейнер можно удалить. RW-слой умрёт вместе с ним. Данные базы в этом слое пропадут.
Named volume живёт отдельно. Удалили контейнер — том на месте, пока явно не сделали down -v.
- Named volume — данные вне контейнера. Для Postgres монтируют в каталог данных, не в корень.
- Bind-mount — папка с хоста. Удобно для кода в dev. В проде легко ошибиться с правами и путём.
- Один том на две базы — способ перезаписать оба датадира.
Пример. Postgres без тома: пересоздали контейнер — база пустая. С named volume pgdata таблицы на месте.
Healthcheck
Процесс стартовал — ещё не значит, что сервис готов. База может накатывать файлы. Api может ждать миграцию.
Healthcheck — команда внутри контейнера: HTTP, TCP, pg_isready. Compose помечает сервис unhealthy. Сосед может подождать.
depends_on без condition: service_healthy ждёт только «контейнер создали и запустили». Api стучится в Postgres слишком рано. Тесты мигают.
Пример. Postgres открыл процесс, но ещё не принимает SQL. Api без healthcheck получает «connection refused» и падает. С service_healthy api стартует, когда pg_isready уже зелёный.
Типичная ошибка
Писать из api в localhost:5432, потому что «порт же проброшен». Внутри контейнера localhost — сам контейнер. Ещё: датадир Postgres в git-папку проекта и один volume на две СУБД.
На собеседовании
Сервисы ходят по имени, не на localhost. Том нужен, чтобы данные пережили контейнер. Healthcheck — «готов принимать запросы», не «процесс жив».