PostgreSQL, également appelé Postgres, est le principal système de base de données objet-relationnel. Il est populaire en raison de son haut niveau de conformité avec la norme SQL et de l’inclusion de fonctionnalités supplémentaires qui simplifient le travail avec des ensembles de données complexes à l’échelle.

PostgreSQL utilise une architecture client-serveur traditionnelle. Vous devez donc l’exécuter indépendamment du code de votre application. Dans ce guide, vous allez déployer une instance de serveur PostgreSQL en tant que conteneur Docker. Cela évite d’ajouter des paquets à votre machine hôte et permet d’isoler votre base de données des autres parties de votre pile. Assurez-vous d’avoir installé Docker avant de continuer.

Mise en route Docker

PostgreSQL a une image officielle sur Docker Hub qui est disponible en plusieurs variantes différentes. Les étiquettes vous permettent de choisir entre les principales versions de PostgreSQL, de la v9 à la v14, et de choisir le système d’exploitation utilisé comme image de base. Alpine, Debian Stretch et Debian Bullseye sont proposées.

Pour les besoins de ce tutoriel, nous utiliserons le tag postgres:14 qui fournit PostgreSQL 14 sur Bullseye. Vous êtes libre de choisir une autre version en fonction de vos besoins.

Démarrez un conteneur PostgreSQL en utilisant la commande docker run :

docker run -d \
–name postgres \
-p 5432:5432
-e POSTGRES_PASSWORD= \
-v postgres:/var/lib/postgresql/data \
postgres:14

Vous devez fournir une valeur pour la variable d’environnement POSTGRES_PASSWORD. Celle-ci définit le mot de passe qui sera attribué au compte superutilisateur par défaut de Postgres. Le nom d’utilisateur par défaut est postgres mais peut être modifié en définissant la variable d’environnement POSTGRES_USER.

L’indicateur -v est utilisé pour monter un volume Docker dans le répertoire de données du conteneur PostgreSQL. Un volume nommé appelé postgres est référencé ; Docker va soit le créer, soit rattacher le volume s’il existe déjà. Vous devriez utiliser un volume pour stocker votre base de données en dehors du conteneur. Sans cela, vous utiliserez vos données lorsque le conteneur s’arrêtera.

PostgreSQL écoute sur le port 5432 par défaut. Le port du conteneur est lié au port 5432 sur votre hôte Docker par l’indicateur -p. L’indicateur -d est utilisé pour démarrer le conteneur en mode détaché, ce qui en fait un service d’arrière-plan qui continue de fonctionner jusqu’à ce qu’il soit arrêté par docker stop.

Fournir le mot de passe sous forme de fichier

Si vous n’êtes pas à l’aise avec l’idée de fournir votre mot de passe de superutilisateur sous la forme d’un drapeau CLI en texte clair, vous pouvez l’injecter dans un fichier via un volume. Vous devez alors définir la variable d’environnement POSTGRES_PASSWORD_FILE pour indiquer à Postgres le chemin d’accès à ce fichier :

docker run -d \
–name postgres \
-p 5432:5432
-e POSTGRES_PASSWORD_FILE=/run/secrets/postgres-password \
-v ./postgres-password.txt:/run/secrets/postgres-password
-v postgres:/var/lib/postgresql/data \
postgres:14

Cette technique fonctionne également pour POSTGRES_USER et les autres variables d’environnement prises en charge.

Connexion à votre base de données

Comme PostgreSQL était lié au port 5432 ci-dessus, vous pouvez vous connecter à votre base de données sur localhost:5432 depuis n’importe quel client compatible. Utilisez les informations d’identification que vous avez attribuées comme variables d’environnement lors du démarrage du conteneur.

L’image Docker inclut également le binaire psql que vous pouvez invoquer avec docker exec. Utilisez-le pour interagir rapidement avec votre base de données à partir d’un shell PostgreSQL dans le conteneur.

docker exec -it postgres psql -U postgres

Connexion à partir d’autres conteneurs Docker

La création d’un réseau Docker est le moyen privilégié d’accéder à PostgreSQL à partir d’autres conteneurs sur le même hôte. Cela évite de lier le port du serveur Postgres et d’exposer potentiellement le service au réseau plus large de votre hôte.

Créez un réseau Docker :

docker network create my-app

Démarrez votre conteneur Postgres avec une connexion au réseau en utilisant l’indicateur –network avec docker run :

docker run -d \
–name postgres \
–network my-app \
-e POSTGRES_PASSWORD= \
-v postgres:/var/lib/postgresql/data \
postgres:14

Joignez maintenant votre conteneur d’application au même réseau :

docker run -d
–name api
–network my-app
mon-api:latest

Les conteneurs du réseau peuvent atteindre Postgres en utilisant le nom d’hôte postgres, car c’est le nom attribué au conteneur Postgres. Utilisez le port 5432 pour établir la connexion.

Configuration de PostgreSQL

Vous pouvez passer les options du serveur PostgreSQL en utilisant les drapeaux -c après le nom de l’image dans votre commande docker run :

docker run -d \
–name postgres \
-p 5432:5432
-e POSTGRES_PASSWORD= \
-v postgres:/var/lib/postgresql/data \
postgres:14 -c max_connections=100

Tout ce qui suit le nom de l’image est transmis à la commande lancée dans le conteneur. Cette commande sera le binaire du serveur PostgreSQL dans le cas de l’image Postgres.

Vous pouvez utiliser un fichier de configuration personnalisé lorsque vous définissez les valeurs de plusieurs options. Vous devrez utiliser un autre volume Docker pour monter votre fichier dans le conteneur, puis fournir un drapeau -c pour indiquer à Postgres où chercher :

docker run -d \
–name postgres \
-p 5432:5432
-e POSTGRES_PASSWORD= \
-v ./postgres.conf:/etc/postgresql/postgresql.conf \
-v postgres:/var/lib/postgresql/data \
postgres:14 -c config_file=/etc/postgresql/postgresql.conf

Cet exemple utilise un montage Docker bind pour que le fichier postgres.conf de votre répertoire de travail soit monté dans le répertoire /etc/postgresql du conteneur. Pour une référence des options que vous pouvez définir avec des drapeaux binaires ou des directives de fichier de configuration, consultez la documentation de PostgreSQL.

Ensemencement de la base de données

L’image Docker prend en charge les fichiers d’amorçage placés dans le répertoire /docker-entrypoint-initdb.d. Tout fichier .sql ou .sql.gz sera exécuté pour initialiser la base de données. Cela se produit après la création du compte utilisateur par défaut et de la base de données postgres. Vous pouvez également ajouter des fichiers .sh pour exécuter des scripts shell arbitraires. Tous les scripts sont exécutés dans l’ordre alphabétique.

Ce mécanisme signifie que tout ce dont vous avez besoin pour amorcer votre base de données est un ensemble de scripts SQL ou shell nommés dans l’ordre séquentiel correct. Montez-les dans votre nouveau conteneur en utilisant le drapeau -v avec docker run :

docker run -d \
–name postgres \
-p 5432:5432
-e POSTGRES_PASSWORD= \
-v ./db-seed-files/:/etc/docker-entrypoint-initdb.d \
-v postgres:/var/lib/postgresql/data \
postgres:14

Les scripts d’initialisation ne seront utilisés que lorsque le répertoire de données Postgres est vide. En pratique, cela signifie qu’ils seront exécutés la première fois que le conteneur démarrera avec un nouveau volume vide attaché.

Création d’une image de base de données personnalisée

Vous pouvez choisir d’encapsuler votre fichier de configuration et vos scripts d’initialisation dans votre propre image Docker. Ainsi, toute personne ayant accès à l’image peut lancer une nouvelle instance PostgreSQL préconfigurée pour votre application. Voici un Dockerfile simple que vous pouvez utiliser :

FROM postgres:14
COPY postgres.conf /etc/postgresql/postgresql.conf
COPY db-seed-files/ /etc/docker-entrypoint-initdb.d/
CMD [« -c », « config_file=/etc/postgresql/postgresql.conf »]

Construisez votre image personnalisée :

docker build -t custom-postgres:latest .

Les instructions de construction dans le Dockerfile copieront le fichier de configuration PostgreSQL et les scripts d’initialisation depuis votre répertoire de travail et les intégreront dans l’image du conteneur. Vous pouvez maintenant démarrer un conteneur de base de données sans fournir manuellement les ressources :

docker run -d \
–name custom-postgres \
-p 5432:5432
-e POSTGRES_PASSWORD= \
-v postgres:/var/lib/postgresql/data \
custom-postgres:latest

Devriez-vous conteneuriser votre base de données de production ?

Il peut être difficile de décider s’il faut exécuter une base de données dans Docker. La conteneurisation de PostgreSQL facilite la mise en place mais est parfois plus difficile à maintenir. Vous devez faire attention à la gestion de votre conteneur pour éviter toute perte de données à l’avenir. Docker ajoute également une modeste surcharge de performance qui vaut la peine d’être prise en compte lorsque vous prévoyez que la base de données de votre tour travaillera avec de très grands volumes de données.

Les avantages de Docker sont une portabilité accrue, une facilité de mise à l’échelle et l’efficacité des développeurs. La conteneurisation de votre base de données permet à quiconque de lancer une nouvelle instance à l’aide de Docker, sans avoir à installer et configurer manuellement PostgreSQL au préalable. L’écriture d’un Dockerfile pour votre base de données PostgreSQL qui ajoute votre fichier de configuration et vos scripts de démarrage SQL est donc un bon moyen d’aider les développeurs à démarrer rapidement de nouveaux environnements.

Résumé

PostgreSQL est un moteur de base de données SQL avancé qui ajoute des fonctionnalités objet-relationnelles. Bien que vous puissiez choisir d’exécuter un déploiement traditionnel en production, l’utilisation d’une instance conteneurisée simplifie la configuration et aide les développeurs à mettre en place rapidement leur propre infrastructure.

L’aspect le plus important d’un déploiement Docker est de s’assurer que vous utilisez un volume pour stocker vos données. Cela vous permettra d’arrêter, de remplacer et de mettre à jour votre conteneur vers une version d’image ultérieure sans perdre votre base de données. Au-delà du stockage, vous devez évaluer comment vous allez vous connecter à Postgres et éviter de lier les ports à votre hôte, sauf si cela est nécessaire. Lorsque vous vous connectez depuis un autre conteneur, il est préférable d’utiliser un réseau Docker partagé pour faciliter l’accès.