Как разместить базу данных в Docker-контейнере, не нарушив целостность данных?

«Как разместить базу данных в Docker-контейнере, не нарушив целостность данных?» — вопрос из категории DevOps, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Основной принцип — отделить данные от контейнера с помощью Docker Volumes или Bind Mounts. Контейнер должен быть эпиhemeral (временным), а данные — persistent (постоянными). В production-среде для Node.js приложений я всегда настраиваю том для данных СУБД.

Способ 1: Named Volumes (рекомендуется для Docker)

# docker-compose.yml для Node.js приложения и PostgreSQL
version: '3.8'
services:
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: strongpassword
    volumes:
      - postgres_data:/var/lib/postgresql/data # Named volume
    networks:
      - app-network

  app:
    build: .
    depends_on:
      - postgres
    environment:
      DATABASE_URL: postgresql://user:strongpassword@postgres:5432/myapp
    networks:
      - app-network

volumes:
  postgres_data: # Volume объявляется здесь

networks:
  app-network:
    driver: bridge

Способ 2: Bind Mounts (для разработки или специфичных путей на хосте)

volumes:
  - ./postgres-data:/var/lib/postgresql/data

Ключевые практики для Node.js окружения:

  1. Используйте .env файлы или секреты Docker для хранения паролей БД, никогда не хардкодьте их.
  2. Настройте регулярные бэкапы самого тома (например, pg_dump в cron-задаче внутри отдельного контейнера).
  3. Для stateful-сервисов в оркестраторах (K8s) используйте PersistentVolumeClaims.
  4. Тестируйте процедуру восстановления из бэкапа на staging-окружении.

Почему это важно: При обновлении образа базы данных или перезапуске контейнера том с данными остается нетронутым. Удаление контейнера postgres не приведет к потере данных, так как они хранятся в volume postgres_data.