PostgreSQL Datenbank im Docker Container upgraden

So gut wie jede Serveranwendung, die ich betreibe, läuft in einem Container. Upgrades sollten auch dementsprechend einfach sein: Aktuelles Image herunterladen, docker-compose down && docker-compose up -d ausführen, und fertig.

Leider klappt das bei PostgreSQL nur bedingt: Während Minor-Versionsupgrades genau so funktionieren, wird man bei Major-Versionsupgrades lediglich mit einer Fehlermeldung begrüßt:

FATAL:   database files are incompatible with server
DETAIL:  The data directory was initialized by PostgreSQL version 11.15, which is not compatible with this version 13.6.

Voraussetzung

Ich gehe im Folgenden davon aus, dass man:

  • Das offizielle PostgreSQL Docker Image verwendet
  • Das Volume nach /var/lib/postgresql/data eingehängt wird
  • Der Benutzer postgres heißt (auf meinen alten Systemen verwende ich noch pgadmin, aber Standard ist das wohl nicht mehr)

Upgrade durchführen

  1. Jede Anwendung, die auf die Datenbank zugreift, beenden. Wer's grafisch mag kann dafür Portainer verwenden, oder wie ich im Terminal via docker-compose down <application name> selektiv Anwendungen herunterfahren. PostgreSQL muss weiterhin laufen!
  2. Dump der Datenbank erstellen: Auch das geht via Portainer, alternativ auch via docker exec. Der Befehl für den Dump lautet pg_dumpall -U postgres > dump.sql. Dieser muss im Container ausgeführt werden!
  3. Anschließend PostgreSQL stoppen
  4. dump.sql aus dem Volume sichern
  5. Das Volume löschen, alternativ für den neuen Container ein anderes Volume verwenden. Hintergrund der Geschichte: PostgreSQL benötigt zwingend ein leeres Verzeichnis für den Start (auch die dump.sql darf sich zum Startzeitpunkt nicht im Volume befinden)
  6. Neues Image ziehen, PostgreSQL Container starten. Auch hier wieder selektiv erst einmal nur PostgreSQL starten, noch keine anderen Anwendungen!
  7. dump.sql in das Volume der Datenbank kopieren/verschieben
  8. Vorher gesicherten Daten importieren. Ich musste feststellen, dass das selbst bei kleinen Datenbanken etwas dauern kann, daher je nach Größe etwas Zeit einplanen. Analog zu Schritt 2 führt man im Container ein psgl -U postgres < dump.sql aus
  9. Nachdem die Datenbank alles import hat, kann man auch die restlichen Anwendungen wieder starten

Das war's :)