Запуск БД внутри контейнера
Контейнер удобен для воспроизводимого локального окружения. Данные БД нужно отделить от контейнера, версию image фиксировать, а готовность проверять не по факту запуска процесса, а healthcheck или реальным запросом.
Локальный PostgreSQL
docker volume create demo-postgres-data
docker run -d \
--name demo-postgres \
-e POSTGRES_DB=demo \
-e POSTGRES_USER=demo_user \
-e POSTGRES_PASSWORD=example-password \
-p 127.0.0.1:5432:5432 \
-v demo-postgres-data:/var/lib/postgresql/data \
--health-cmd='pg_isready -U demo_user -d demo' \
--health-interval=5s \
--health-retries=10 \
postgres:16Пароль здесь учебный. Реальный secret не храню в заметке, Dockerfile или истории shell.
Проверка:
docker inspect demo-postgres --format '{{.State.Health.Status}}'
docker logs --tail 100 demo-postgres
docker exec -it demo-postgres \
psql -U demo_user -d demoCompose
services:
db:
image: postgres:16
environment:
POSTGRES_DB: demo
POSTGRES_USER: demo_user
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U demo_user -d demo"]
interval: 5s
timeout: 3s
retries: 10
volumes:
db-data:Инициализационные переменные официального image обычно действуют только при создании пустого data directory. Изменение POSTGRES_PASSWORD при уже заполненном volume не обязательно меняет пароль существующего пользователя.
Production-ограничения
Сам container не решает backup, репликацию, failover, upgrade и наблюдаемость. Для production нужны проверенная стратегия хранения, восстановление из backup, ограничение доступа, план миграции версии и мониторинг ресурсов.
Типичные сбои
- Приложение подключается раньше, чем БД готова принимать запросы.
- После смены environment старый volume сохраняет прежнее состояние.
- Порт опубликован на всех интерфейсах без необходимости.
- Используется
latest, и локальная схема внезапно запускается на другой major version. - Volume удалён вместе с Compose-проектом.
Вопросы для собеседования
Почему контейнеризация не делает БД stateless? Состояние остаётся в data directory и требует отдельного жизненного цикла.
Зачем healthcheck, если container running? Running говорит о PID 1, но не о готовности принимать запросы.
Почему новая переменная пароля могла не сработать? Инициализация уже прошла на непустом volume.
Нужно ли публиковать порт БД? Только если к ней обращаются с host или извне; внутри сети Compose достаточно service name.