Running with Persistent Storage
Running with Persistent Storage
Postgres keeps everything under one directory, so mounting that directory is non-negotiable:
docker run -d --name pg \
-e POSTGRES_PASSWORD=devpass \
-e POSTGRES_DB=app \
-v pgdata:/var/lib/postgresql/data \
-p 5432:5432 \
postgres:16
The entrypoint initializes the cluster on first boot, creates the database, and starts the server on 5432. Pair it with a health check the orchestrator can consume:
docker exec pg pg_isready -U postgres
Without the named volume, docker rm destroys the cluster with the container — the classic way to lose a demo dataset.
Configuration for Containers
Configuration for Containers
Container Postgres shares RAM with the app, so defaults sized for a dedicated host are wrong. Override at launch or via a mounted config:
docker run -d --memory 2g postgres:16 \
-c shared_buffers=512MB \
-c max_connections=100 \
-c effective_cache_size=1536MB
Common starting points: shared_buffers near a quarter of container memory, effective_cache_size describing what the OS cache is expected to contribute, and max_connections sized below what the pooler and memory allow — connection storms are better absorbed by PgBouncer than by raising the limit. Persist settings with -c flags or an postgresql.conf mount, never by exec-ing ALTER SYSTEM that no one can review.
Backups and Pitfalls
Backups and Pitfalls
Logical backups run inside the container:
docker exec pg pg_dump -U postgres -Fc app > app.dump
docker exec -i pg pg_restore -U postgres -d app_recovered < app.dump
-Fc (custom format) supports parallel restore and selective -t table recovery. Schedule it from the host, not from a container that dies with the cluster.
Pitfalls. Files in /docker-entrypoint-initdb.d run only when the data directory is empty — schema edits to them silently do nothing on a live volume. fsync=off speeds bulk loads but can corrupt after a hard stop: dev-only.
Interview: walk first-boot initialization, name the volume path you protect, and contrast pg_dump with physical base backups for point-in-time recovery.
Quiz
1. When do scripts in /docker-entrypoint-initdb.d execute?
2. What does pg_isready tell an orchestrator?
3. Why is raising max_connections often the wrong fix for load?
Flashcards
Question
Data directory
Click to reveal answer
Answer
/var/lib/postgresql/data — mount it to a named volume or data dies with the container.
Question
shared_buffers
Click to reveal answer
Answer
Postgres's own cache, typically ~25% of container memory; effective_cache_size estimates the OS cache.
Question
pg_dump -Fc
Click to reveal answer
Answer
Custom-format dump: compressed, parallel and table-selective restore.
Question
pg_isready
Click to reveal answer
Answer
Connection probe used for health checks and service_healthy dependencies.
Revision Notes
Key Takeaways
- 1. A named volume on /var/lib/postgresql/data is mandatory
- 2. Size shared_buffers and max_connections to the container, not the host
- 3. Init scripts run once, on an empty datadir only
Interview Tips
- • Explain first boot: entrypoint → init scripts → permanent settings
- • Contrast logical dump restore with physical backup/PITR and when each applies
Cheat Sheet
postgres:16 + -v pgdata:/var/lib/postgresql/data; -c shared_buffers ≈25% RAM; healthcheck pg_isready; pg_dump -Fc scheduled outside the container.
Continue Learning
Before You Start
- No prerequisites listed.