PostgreSQLXVIII · Platforms, Corruption and Production ArchitecturePlatforms
PostgreSQL in containers: what a container does not solve
What you'll learn
- Identify what containerisation changes and what it does not
- Read memory limits correctly from inside a container
- Handle data persistence and signals deliberately
- Avoid the container-specific traps met in this course
Prerequisites
Verified against PostgreSQL 18.x · PostgreSQL (comparison targets) 17.11, 16.15 · PostgreSQL (support calendar) 18, 17, 16, 15, 14 supported · pgBackRest 2.59.1 · PgBouncer 1.25.2 · Patroni 4.1.5 · Ubuntu (host baseline) 26.04 LTS · 2026-08-27
Every measurement in this course was taken in a container. That is a reasonable way to run PostgreSQL, and it introduces a specific set of traps — most of which this course walked into while producing its own evidence.
What a container changes
Packaging. One image, the same everywhere, with the version pinned.
Isolation. Resource limits, network namespace, filesystem namespace.
Lifecycle. Start, stop and restart become orchestration events rather than service-manager events.
What it does not change
Everything in Parts VI to XVII. Storage, MVCC, vacuum, locks, the planner, memory, WAL, backups, replication, upgrades — a container is still running the same PostgreSQL, and every measurement in those parts was taken inside one.
Signals and PID 1
PostgreSQL’s shutdown modes from lesson XII-07 map onto signals:
SIGTERM is smart, SIGINT is fast, SIGQUIT is immediate.
A container runtime sends SIGTERM on stop, waits, then SIGKILL.
SIGTERM is the smart shutdown — which lesson XII-07 measured
failing after 10 seconds while sessions remained connected, with
pg_ctl: server does not shut down.
Data persistence
Never keep data in the container’s writable layer. It is destroyed with the container.
This course met the consequence directly. A docker commit of a
PostgreSQL container captured no data at all, because the image
declares /var/lib/postgresql as a volume and commit does not include
volume contents:
$ docker commit rbpg-prim rbpg-prim-snap && docker run ... rbpg-prim-snap pg_controldata $PGDATApg_controldata: error: could not open file
"/var/lib/postgresql/18/docker/global/pg_control" for reading:
No such file or directoryThe fix was to mount the original volume into the new container by name. The general rule: the volume is the database; the container is disposable.
Configuration precedence
The official image is started with -c setting=value command-line
arguments. Lesson XIII-05 measured the consequence:
$ SELECT name, setting, source FROM pg_settings WHERE name = 'archive_command'; name | setting | source
-----------------+--------------------------------------------+--------------
archive_command | test ! -f /archive/%f && cp %p /archive/%f | command lineALTER SYSTEM wrote postgresql.auto.conf and reported success. The
setting did not change, because command-line arguments outrank it.
Always confirm with pg_settings.source, not with the file
contents. This is a container-specific hazard precisely because the
official image uses command-line arguments as its configuration
mechanism.
What still needs solving
A container gives you none of:
- Backups. Part XIII.
- Replication and failover. Parts XIV and XV.
- Monitoring. Part XVI.
- Storage durability — an image says nothing about whether the volume’s fsync is honest. Lesson VI-01.
- Connection pooling. Lesson IV-06.
What to take from this
- A container changes packaging, isolation and lifecycle. It changes nothing about PostgreSQL’s behaviour.
freereports the host’s memory. Read/sys/fs/cgroup/memory.maxand size from that.SIGTERMis the smart shutdown, which can fail to complete. SetSTOPSIGNAL SIGINTand a generous stop timeout, or every stop is a crash.- The volume is the database.
docker commitcaptures no volume data — measured. - The official image configures via command-line arguments, which
outrank
ALTER SYSTEM. Checkpg_settings.source. - Containers give you no backups, replication, monitoring, durable storage or pooling.
Cross-course references
- Docker & Containers — Part VIII (Storage) covers volume lifetime against container lifetime, Part VI (Container lifecycle) covers the stop-then-kill sequence that makes crash recovery routine, and Part XV (Resource controls) covers the memory limit the OOM killer uses.
- Linux for Production Sysadmins — Part LXXVIII (Containers from the Linux perspective) covers what a container actually is, which is what makes the “it does not solve durability” argument concrete.
Quiz
Knowledge check · 6 questions
Q1. A monitoring agent inside a container reports 40 GB of memory free, and the container is then OOM-killed. Why?
Q2. A containerised PostgreSQL performs crash recovery on every start, even though every stop was a normal orchestrated stop. What is the cause?
Q3. Why did docker commit of a PostgreSQL container produce an image with no database in it?
Q4. Which container ecosystem defaults fit a database badly? Select all that apply.
Q5. On the official PostgreSQL image, ALTER SYSTEM reliably changes any setting because it writes postgresql.auto.conf.
Q6. What does containerising PostgreSQL solve, and what does it leave entirely unsolved?
Passing score: 75%. Answers are checked in this browser.