Запуск БД внутри контейнера

Контейнер удобен для воспроизводимого локального окружения. Данные БД нужно отделить от контейнера, версию 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 demo

Compose

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.

См. Docker Volume, Bridge Network Мостовая сеть Docker.