Полное руководство по развёртыванию PostgreSQL с помощью Docker Compose — конфигурация для production, сохранение данных, бэкапы и безопасность. Примерное время выполнения: 45–90 минут.
0
Статья была полезной?
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…
Вы получите рабочий production-ready стек PostgreSQL в Docker Compose с автоматическим созданием базы, политиками перезапуска, примерами бэкапа и восстановления. На выполнение этих шагов уйдёт от 45 до 90 минут в зависимости от скорости канала и железа.
Что вы изучите
Как собрать compose-файл для PostgreSQL 16 (релиз 2024) с production-параметрами.
Как правильно хранить данные в volume и решать проблемы с правами.
Как настроить и автоматизировать бэкапы через pg_dump и экспорт WAL-архивов.
Как использовать init-скрипты и безопасно хранить секреты в .env.
Рекомендации по ресурсам: RAM, CPU, размеры образов и порты.
Требования
Операционная система: Ubuntu 22.04 LTS или CentOS Stream 9 / Debian 12, ядро Linux с поддержкой overlay2.
Docker Engine: 24.0+ (релиз 2025), Docker CLI с поддержкой docker compose (Compose v2.20+).
Свободный диск: минимум 10 ГБ; для production рекомендуются 50+ ГБ под DB-файлы и архивацию WAL.
RAM: минимум 2 ГБ для небольших нагрузок, рекомендовано 4 ГБ+ для рабочей нагрузки; CPU: 2 vCPU минимум.
PostgreSQL: образ postgres:16 (образ full ~380MB, slim/alpine ~60–120MB с 2025 года). Порт: 5432.
Зачем Docker для PG?
Docker упрощает развёртывание PostgreSQL: одинаковая среда на dev/staging/production, быстрый rollback и возможность версионировать образ. Контейнеры облегчают управление зависимостями и позволяют отделить жизненный цикл СУБД от хоста. С Compose вы описываете конфигурацию как код, что полезно для CI/CD (например, GitHub Actions) и для воспроизводимости развёртываний.
Базовый compose
Ниже минимальный, но production-ориентированный пример docker-compose.yml для PostgreSQL 16 с томом для данных, healthcheck и политикой перезапуска.
Размеры образов: postgres:16 full ≈ 380MB, slim/alpine варианты ≈ 60–120MB (сжатый). Ожидаемое время загрузки образа на типичном канале 100 Мбит/с — 10–30 секунд для slim, 30–120 секунд для полного образа.
Файловая структура проекта с docker-compose и initdb
Как сохранить данные?
Для долговременного хранения данных используйте Docker volumes или bind-mount на LVM/XFS. Volume защищает от случайного удаления файлов хоста и работает лучше для миграций. В production лучше использовать отдельный диск с размонтированной файловой системой и логическим томом.
Шаг 1: создать структуру проекта
Команды: создайте каталог, файл compose и папку initdb для начальных SQL-скриптов.
Пояснение: структура обеспечивает изоляцию проекта и удобство для CI/CD. Файл .env будет содержать чувствительные параметры и не должен попадать в репозиторий.
Ожидаемый вывод:
$ ls -la
total 16
drwxr-xr-x 4 user user 4096 Apr 10 2026 .
drwxr-xr-x 3 user user 4096 Apr 10 2026 ..
drwxr-xr-x 2 user user 4096 Apr 10 2026 initdb
-rw-r--r-- 1 user user 0 Apr 10 2026 .env
-rw-r--r-- 1 user user 0 Apr 10 2026 docker-compose.yml
Типичная ошибка: Permission denied при создании папок. Фикс:
Пояснение: Compose автоматически подхватит переменные из .env. Установка прав 600 предотвращает просмотр файла другими пользователями.
Ожидаемый вывод:
$ ls -la .env
-rw------- 1 user user 34 Apr 10 2026 .env
Типичная ошибка: забыли выставить права, файл попал в git. Фикс: добавьте .env в .gitignore и пересоздайте секреты через менеджер секретов (Vault, AWS Secrets Manager) для production.
Шаг 3: запустить compose и проверить контейнер
Команда: запустите стек и проверьте состояние сервиса.
docker compose up -d --no-recreate
# Проверить логи и статус
docker compose ps
docker compose logs -f db --tail=50
Пояснение: параметр --no-recreate предотвращает пересоздание контейнеров. Healthcheck в compose поможет системе определить готовность.
Ожидаемый вывод:
$ docker compose ps
Name Command State Ports
--------------------------------------------------------------------------------
project_db_1 docker-entrypoint.sh postgres Up (healthy) 0.0.0.0:5432->5432/tcp
$ docker compose logs db --tail=5
db_1 | PostgreSQL init process complete; ready for start up.
db_1 | 2026-04-10 10:12:03.123 UTC [1] LOG: database system is ready to accept connections
Типичная ошибка: "Cannot connect to the Docker daemon". Фикс: убедитесь, что Docker запущен: sudo systemctl start docker или добавьте пользователя в группу docker и перелогиньтесь.
Статус контейнера PostgreSQL в docker compose
Шаг 4: проверить подключение и init-скрипты
Команды: выполните psql внутри контейнера, создайте тестовую таблицу и убедитесь, что init-скрипты выполнены.
# зайти в контейнер и запустить psql
docker compose exec db psql -U myapp -d myapp -c "SELECT version();"
# пример запуска init скрипта (файл initdb/01_create_extensions.sql)
cat > initdb/01_create_extensions.sql <<SQL
CREATE EXTENSION IF NOT EXISTS pgcrypto;
SQL
Ожидаемый вывод:
$ docker compose exec db psql -U myapp -d myapp -c "SELECT version();"
version
------------------------------------------------------------------------------------------------------
PostgreSQL 16.3 (Debian 16.3-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
(1 row)
Типичная ошибка: init-скрипты не выполняются при повторном старте (они выполняются только при инициализации пустого каталога данных). Фикс: для тестирования удалите volume или используйте новую папку данных. Для production используйте отдельный контейнер/процесс миграций (например, Flyway или миграции в CI).
Шаг 5: настроить бэкапы и восстановление
Команды: ручный бэкап и восстановление с помощью pg_dumpall. Включён пример cron-команды и проверка целостности.
# ручный бэкап всех БД
docker compose exec db pg_dumpall -U myapp > ~/backups/myapp-$(date +%F).sql
# восстановление
cat ~/backups/myapp-2026-04-10.sql | docker compose exec -T db psql -U myapp
Пояснение: pg_dumpall даёт текстовый дамп ролей и схем; для больших БД используйте pg_dump -Fc или репликацию с WAL и pg_basebackup. Рекомендуемый cron: ежедневный дамп в 03:00, ротация 14 дней, полный резерв на удалённое хранилище (S3 или NFS).
Ожидаемый вывод:
$ ls -lh ~/backups/myapp-2026-04-10.sql
-rw-r--r-- 1 user user 12M Apr 10 03:02 myapp-2026-04-10.sql
$ head -n 5 ~/backups/myapp-2026-04-10.sql
-- PostgreSQL database dump
-- Dumped from database version 16.3
-- Dumped by pg_dump version 16.3
Типичная ошибка: authentication failed (пароль). Фикс: проверьте переменные окружения, .pgpass или используйте флаг -U с корректным пользователем. Для автоматизации бэкапов на хосте используйте системd-таски и mount точки для бэкап-каталога.
Шаг 6: доступ из приложений и сетевые настройки
Команда: протестируйте подключение с хоста или с другого контейнера.
# из хоста, если порт проброшен
PGPASSWORD=StrongPassw0rd!2026 psql -h 127.0.0.1 -p 5432 -U myapp -d myapp -c "SELECT 1;"
# из другого сервиса внутри сети compose
docker compose run --rm app psql postgresql://myapp:$(grep POSTGRES_PASSWORD .env | cut -d'=' -f2)@db:5432/myapp -c "SELECT 1;"
Ожидаемый вывод:
?column?
----------
1
(1 row)
Типичная ошибка: connection refused. Фикс: проверьте проброс порта (5432:5432), firewall (ufw/iptables) и параметр listen_addresses в postgresql.conf (по умолчанию контейнер слушает 0.0.0.0).
Шаг 7: мониторинг и аптайм
Рекомендация: установите минимальный мониторинг — check readiness и alert при падении healthcheck. Используйте Prometheus + pg_exporter или простой healthcheck через pg_isready. Пример systemd unit для периодической проверки:
[Unit]
Description=Check postgres in compose
[Service]
Type=oneshot
ExecStart=/usr/bin/docker compose -f /home/user/projects/postgres-compose/docker-compose.yml exec db pg_isready -U myapp
[Install]
WantedBy=multi-user.target
Пояснение: systemd unit позволяет интегрировать проверку в стандартный мониторинг хоста и запускать alert-скрипты при сбое.
Для production-PostgreSQL в контейнере ключевые вещи: правильное хранение данных на SSD, регулярные бэкапы и контроль прав на файлы.
Частые вопросы
как обеспечить устойчивость данных при отказе узла?
Используйте внешний том на отдельном диске (LVM или отдельный SSD), настройте репликацию (streaming replication) на уровне PostgreSQL и храните WAL на удалённом хранилище. Для простого сценария Docker Compose можно настроить репликацию между несколькими инстансами PostgreSQL в разных хостах, но для production рекомендуется Kubernetes/Patroni или управляемый сервис. Также автоматизируйте бэкапы и проверяйте их восстановимость регулярно.
что делать с секретами в Compose — .env безопасно?
.env удобен для разработки, но не безопасен в production. Для production используйте менеджер секретов (HashiCorp Vault, AWS Secrets Manager) или docker secrets в Swarm/Kubernetes. Если приходится использовать .env, храните его с правами 600 и не добавляйте в VCS; рассчитайте ротацию паролей и храните лог доступа для аудита.
почему init-скрипты не выполняются снова после перезапуска?
Docker-entrypoint PostgreSQL выполняет скрипты из /docker-entrypoint-initdb.d только при первой инициализации данных (когда каталог данных пуст). Для повторного выполнения удалите том с данными (только в тестовых окружениях) или выполните скрипты ручным запуском через docker compose exec db psql -U user -d db -f /path/script.sql или управляйте миграциями отдельным процессом в CI/CD.
где хранить бэкапы и сколько их держать?
Бэкапы храните на удалённом хранилище — S3/Minio или NFS, с версионированием и ротацией. Резервную политику 14–30 дней достаточно для большинства приложений; критические данные требуют более длительного хранения и offsite-репликации. Размер дампа зависит от объёма БД: при 50 ГБ данных текстовый дамп может занимать 30–50 ГБ, compressed dump (pg_dump -Fc) обычно в 2–5 раз меньше.
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…