Upgrade de version majeure d'une BDD Postgres avec Docker
Je voulais mettre à jour mon TeslaMate de la version 1.26.1 vers la 1.27.1. Simple, avec Docker, mais au moment de pull/up -d, le container de BDD me crache l'erreur suivante à la figure :
postgres_1 | FATAL: database files are incompatible with server
postgres_1 | DETAIL: The data directory was initialized by PostgreSQL version 13, which is not compatible with this version 14.6.
C'est assez clair comme explication : les données ont été créées avec une version antérieure de Postgres et ne sont pas compatibles avec la nouvelle version. Mettons-nous au travail pour upgrade les datas dans la bonne version.
En fait la procédure est assez simple sur le papier :
- On BACKUP (toujours toujours toujours)
- On détruit les données (on a un backup, NORMALEMENT) ainsi que le container Postgres en version 13
- On recréé un container Postgres en version 14
- On restore le backup
Dans les faits, ça donne :
On dump la BDD (On fait une sauvegarde, quoi)
docker-compose exec -T database pg_dump -U teslamate teslamate > ./backup/teslamate.bck
On stoppe la stack docker teslamate (On a pas envie qu'un container écrive dans la BDD pendant qu'on manipe) et on dégage les container, tant qu'à faire. De toute façon on va mettre à jour.
docker-compose down
On supprime le dossier ./data/db ou se trouvent les données de la DB
rm -R ./data/db
On modifie le docker-compose.yml pour y mettre à jour les versions des images (Je reste en 1.26 pour teslamate pour l'instant, afin de ne pas télescoper les manips sur la BDD avec des migrations de la nouvelle version 1.27). En somme on modifie
image: postgres:13
en
image: postgres:14
Le fichier complet :
version: "3"
services:
teslamate:
image: teslamate/teslamate:1.26
restart: always
environment:
- DATABASE_USER=teslamate
- DATABASE_PASS=MoNp@sSw0rdSuPerfOrt
- DATABASE_NAME=teslamate
- DATABASE_HOST=database
- MQTT_HOST=mosquitto
- ENCRYPTION_KEY=unecledechiffrementtreslonguepourchiffremontokenperso
- VIRTUAL_HOST=teslamate.caliko.net
- VIRTUAL_PORT=4000
- LETSENCRYPT_EMAIL=dorian@email.com
- LETSENCRYPT_HOST=teslamate.caliko.net
ports:
- 4000:4000
volumes:
- ./import:/opt/app/import
cap_drop:
- all
database:
image: postgres:14
restart: always
environment:
- POSTGRES_USER=teslamate
- POSTGRES_PASSWORD=MoNp@sSw0rdSuPerfOrt
- POSTGRES_DB=teslamate
volumes:
- ./data/db:/var/lib/postgresql/data
graf:
image: teslamate/grafana:1.26
restart: always
environment:
- DATABASE_USER=teslamate
- DATABASE_PASS=MoNp@sSw0rdSuPerfOrt
- DATABASE_NAME=teslamate
- DATABASE_HOST=database
- VIRTUAL_HOST=teslagraf.caliko.net
- VIRTUAL_PORT=3000
- LETSENCRYPT_EMAIL=dorian@email.com
- LETSENCRYPT_HOST=teslagraf.caliko.net
ports:
- 3000:3000
volumes:
- ./data/grafana:/var/lib/grafana
mosquitto:
image: eclipse-mosquitto:2
restart: always
command: mosquitto -c /mosquitto-no-auth.conf
expose:
- 1883
volumes:
- ./conf/mosquitto:/mosquitto/config
- ./data/mosquitto:/mosquitto/data
networks:
default:
external:
name: reverse-proxy
Une fois que c'est fait, je commence par lancer uniquement le container postgres :
docker-compose up -d database
J'attends quelques secondes que tout s'initialise (le serveur va démarrer et lancer les premières actions sur la DB pour l'initialiser, je rappelle qu'on a tout supprimé. Mais on a un backup ! )
Une fois démarré (on peut faire un docker logs teslamate_database_1 pour voir ce qui se passe), on supprime le schéma initial (Pas forcément nécessaire, mais dans le doute, je repars raiment de 0) :
docker-compose exec -T database psql -U teslamate << .
drop schema public cascade;
create schema public;
create extension cube;
create extension earthdistance;
CREATE OR REPLACE FUNCTION public.ll_to_earth(float8, float8)
RETURNS public.earth
LANGUAGE SQL
IMMUTABLE STRICT
PARALLEL SAFE
AS 'SELECT public.cube(public.cube(public.cube(public.earth()*cos(radians(\$1))*cos(radians(\$2))),public.earth()*cos(radians(\$1))*sin(radians(\$2))), public.earth()*sin(radians(\$1)))::public.earth';
.
Le résultat :
On importe maintenant le backup fait en première étape
docker-compose exec -T database psql -U teslamate -d teslamate < ./backup/teslamate.bck
Là, en fonction de la taille du backup ça peut être plus ou moins long. Pas mal de choses vont défiler à l'écran, pas de panique si rien ne se passe pendant quelques secondes. L'important, c'est qu'au moment ou le prompt est rendu, on n'ait aucune erreur affichée. Sinon, il faut analyser pourquoi.
Maintenant on a un container Postgres en version 14, avec les données utilisables.
Je stoppe et supprime le container avec un docker-compose down puis je lance la stack complète avec docker-compose up -d
J'ai maintenant un TeslaMate en version 1.26.1 et une BDD Postgres en version 14. Reste à mettre à jour TeslaMate, et là c'est bien plus simple. On reprend notre fichier docker-compose.yml et on change les tags teslamate/teslamate:1.26 et teslamate/grafana:1.26 pour les passer en version 1.27.
Un docker-compose up -d plus tard, nous voilà avec le tout à jour !


No Comments