PostgreSQL в Docker
Раздел 8.11, шаг 7 из 12. Дальше — облако и Kubernetes.
Базовый запуск
Официальный образ — hub.docker.com/_/postgres.
docker run -d \
--name pg-dev \
-e POSTGRES_USER=app \
-e POSTGRES_PASSWORD=secret \
-e POSTGRES_DB=appdb \
-p 5432:5432 \
-v pgdata:/var/lib/postgresql/data \
postgres:16-alpine
| Переменная | Смысл |
|---|---|
POSTGRES_USER / POSTGRES_PASSWORD | Суперпользователь (default postgres) |
POSTGRES_DB | БД, создаваемая при init |
PGDATA | Путь к данным внутри контейнера (default /var/lib/postgresql/data) |
Init-скрипты — монтируйте .sql / .sh в /docker-entrypoint-initdb.d/ (выполняются только при первом создании volume).
Volume — обязательное правило
Без named volume или bind-mount данные исчезают при удалении контейнера.
# docker-compose.yml
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: appdb
volumes:
- pgdata:/var/lib/postgresql/data
- ./init:/docker-entrypoint-initdb.d:ro
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d appdb"]
interval: 5s
timeout: 3s
retries: 5
command:
- "postgres"
- "-c"
- "shared_buffers=256MB"
- "-c"
- "log_min_duration_statement=200ms"
volumes:
pgdata:
healthcheck с pg_isready — приложение должно ждать depends_on: condition: service_healthy (Compose v2+).
Сеть и несколько контейнеров
services:
api:
build: .
environment:
DATABASE_URL: postgres://app:${DB_PASSWORD}@db:5432/appdb
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
# …
pgbouncer:
image: edoburu/pgbouncer
environment:
DATABASE_URL: postgres://app:${DB_PASSWORD}@db:5432/appdb
POOL_MODE: transaction
ports:
- "6432:5432"
depends_on:
db:
condition: service_healthy
Имя сервиса db — DNS внутри compose-сети. Приложение подключается к PgBouncer, Postgres остаётся internal.
Кастомный конфиг
Вариант 1 — command: postgres -c key=val (см. выше).
Вариант 2 — смонтировать файл:
volumes:
- ./postgresql.conf:/etc/postgresql/postgresql.conf:ro
command: postgres -c config_file=/etc/postgresql/postgresql.conf
На production в контейнере часто минимальный конфиг + override через orchestrator.
Типовые ошибки
| Ошибка | Последствие | Решение |
|---|---|---|
| Данные в writable layer | Потеря при recreate | Named volume |
docker-compose down -v в CI | Удаление volume | Отдельный volume для prod |
| Один контейнер = prod БД без бэкапа | Потеря данных | шаг 10, managed или Patroni |
fsync=off «для скорости» | Корruption при crash | Только ephemeral dev |
| Root в контейнере + широкие права на volume | Риск безопасности | User namespace, POSTGRES_INITDB_ARGS=--auth-host=scram-sha-256 |
Один Docker-контейнер с Postgres подходит для dev/stage и учебных стендов. Production HA — репликация, Patroni или managed-сервис (шаги 8–9).
Образы и версии
-alpine— меньше размер, иногда проблемы с локалями и расширениями.- Pinning —
postgres:16.4-alpine, неlatest. - Расширения (PostGIS) — образы
postgis/postgisили сборка своего Dockerfile:
FROM postgres:16-alpine
RUN apk add --no-cache postgis
Миграция данных в/из контейнера
docker exec -t pg-dev pg_dump -U app -Fc appdb > backup.dump
docker exec -i pg-dev pg_restore -U app -d appdb < backup.dump
Логический dump переносим между версиями (с оговорками major upgrade).
Практика
- Поднимите compose с api + postgres + healthcheck; подключитесь через phpPgAdmin или psql.
- Убейте контейнер
db, пересоздайте — данные должны сохраниться в volume. - Добавьте PgBouncer, прогоните нагрузку через
pgbenchна 6432.
Связанные материалы
См. также
Другие статьи этого же раздела в боковом меню (как на странице "О разделе"). MVCC, XID, снимки данных, системные поля xmin/xmax, VACUUM и autovacuum, bloat, wraparound, процессы postmaster, Shared Buffers и WAL. pg_dump, pg_basebackup, PITR, pg_probackup, Wal-G, стратегия 3-2-1, восстановление в Kubernetes и после failover. pg_stat_statements, pg_stat_activity, auto_explain, pgBadger, Prometheus postgres_exporter, типовые метрики SLA и алерты. Ansible role для установки Postgres, шаблоны postgresql.conf, Terraform для RDS и managed PostgreSQL, GitOps паттерны для инфраструктуры БД. EXPLAIN и EXPLAIN ANALYZE, B-tree, GiST, SP-GiST, GIN, BRIN, частичные и составные индексы, типовые ошибки планировщика. Тонкая настройка памяти (shared_buffers, work_mem, maintenance_work_mem), I/O (effective_cache_size, random_page_cost), WAL, checkpoint и autovacuum. Документная модель в Postgres, операторы и индексы JSONB, declarative partitioning по range/list/hash, связь с оконными функциями и CTE. Хранимые функции и процедуры PL/pgSQL, row-level и statement triggers, event triggers, асинхронные события через NOTIFY и LISTEN без polling. Streaming replication, logical replication, read replicas и Hot Standby, failover, connection pooling через PgBouncer — transaction и session pooling. Managed PostgreSQL (RDS, Cloud SQL, Yandex Managed), StatefulSet, PersistentVolume, секреты, операторы Crunchy/Zalando, anti-patterns stateful в K8s. Patroni и DCS, сравнение с Greenplum и CockroachDB, когда нужен sharding, Citus, выбор архитектуры под OLTP и аналитику. Краткое резюме раздела 8.11 — архитектура, оптимизация, эксплуатация в контейнерах и Kubernetes, HA, бэкапы и автоматизация.Архитектура PostgreSQL и внутреннее устройство
Бэкапы PostgreSQL и восстановление
Профилирование и мониторинг PostgreSQL
Автоматизация PostgreSQL — Ansible и Terraform
Продвинутая оптимизация PostgreSQL и индексы
Конфигурация PostgreSQL — postgresql.conf
JSONB, партиционирование и расширения SQL в PostgreSQL
PL/pgSQL, триггеры и NOTIFY/LISTEN в PostgreSQL
Репликация PostgreSQL, Hot Standby и PgBouncer
PostgreSQL в облаке и Kubernetes
HA-кластеры PostgreSQL и распределённые СУБД
Практикум PostgreSQL — итоги