You are currently viewing Docker Hub PostgreSQL : décryptage des images officielles

Docker Hub PostgreSQL : décryptage des images officielles

  • Auteur/autrice de la publication :
  • Post category:DevOps

Dans cet article

  • L’image officielle postgres sur Docker Hub cumule plus de 1 milliard de téléchargements et reste la référence pour déployer PostgreSQL en conteneur
  • Les tags Alpine réduisent la taille de l’image de près de 70 % par rapport aux tags Debian classiques
  • Les variables d’environnement POSTGRES_PASSWORD, POSTGRES_USER et POSTGRES_DB suffisent à configurer un conteneur fonctionnel en quelques secondes
  • Les images Bitnami et Ubuntu proposent des approches alternatives avec des couches de sécurité supplémentaires
  • Un fichier docker-compose.yml bien structuré permet de gérer la persistance des données et le réseau en production
  • Le choix du tag PostgreSQL dépend de votre besoin : stabilité, légèreté ou conformité aux standards de votre organisation

Quand j’ai commencé à utiliser Docker pour mes projets de bases de données, la première chose que j’ai tapée dans la barre de recherche de Docker Hub, c’est « postgresql ». Et je me suis retrouvée face à des dizaines d’images, de tags et de variantes. Entre l’image officielle postgres, les déclinaisons Alpine, les images Bitnami ou Ubuntu, le choix peut sembler déroutant. Après des années à déployer des serveurs PostgreSQL en conteneurs pour mes étudiants en BTS SIO et pour mes clients, je vous propose un décryptage complet de ce que Docker Hub propose réellement pour PostgreSQL.

Comprendre les images officielles PostgreSQL sur Docker Hub

L’image officielle postgres sur Docker Hub est maintenue par le projet Docker Library en collaboration avec la communauté PostgreSQL. C’est la référence absolue quand on cherche à déployer un serveur PostgreSQL conteneurisé. Elle est identifiable par le badge « Docker Official Image » qui garantit un certain niveau de qualité, de documentation et de suivi des mises à jour de sécurité.

Cette image est construite à partir du dépôt GitHub docker-library/postgres où chaque Dockerfile est versionné et auditable. Je recommande toujours à mes étudiants de consulter ce dépôt pour comprendre exactement ce qui se passe à l’intérieur de l’image. C’est un excellent exercice pédagogique qui permet de démystifier le fonctionnement des conteneurs.

Concrètement, quand vous exécutez docker pull postgres, vous récupérez l’image basée sur Debian Bookworm avec la dernière version stable de PostgreSQL. Le conteneur expose le port 5432 par défaut et attend au minimum la variable POSTGRES_PASSWORD pour démarrer. C’est un choix de sécurité : impossible de lancer un serveur PostgreSQL sans mot de passe, même en développement.

Exécution des commandes Docker pour déployer un conteneur PostgreSQL
Exécution des commandes Docker pour déployer un conteneur PostgreSQL

L’image officielle intègre également un mécanisme d’initialisation très pratique : tout script SQL ou shell placé dans le répertoire /docker-entrypoint-initdb.d/ sera exécuté automatiquement au premier démarrage du conteneur. J’utilise cette fonctionnalité systématiquement pour créer mes schémas de base, insérer des données de test ou configurer des extensions comme pgcrypto ou uuid-ossp.

Anatomie des tags et versions disponibles

La politique de tags de l’image officielle postgres suit une logique précise qu’il faut bien comprendre pour éviter les mauvaises surprises en production. Voici comment je décode les tags principaux :

Le tag postgres:latest pointe toujours vers la dernière version majeure stable. Au moment où j’écris ces lignes, cela correspond à PostgreSQL 17. Mais attention : utiliser latest en production est une erreur classique que je vois chez beaucoup de débutants. Une mise à jour majeure automatique peut casser la compatibilité avec vos données existantes.

Les tags numériques comme postgres:16, postgres:15 ou postgres:14 pointent vers la dernière version mineure de la branche majeure concernée. C’est le bon compromis entre stabilité et mises à jour de sécurité. Pour aller encore plus loin dans le verrouillage, vous pouvez spécifier la version mineure exacte : postgres:16.4 par exemple.

Les variantes Alpine (postgres:16-alpine) utilisent Alpine Linux comme système de base au lieu de Debian. Le résultat est spectaculaire en termes de taille : une image Alpine pèse environ 80 Mo contre 250 Mo pour la variante Debian. Pour un environnement de développement ou un réseau Docker Compose avec plusieurs services, cette économie est significative.

Il existe aussi des tags avec le suffixe -bookworm ou -bullseye qui précisent la version de Debian utilisée. Cette granularité est utile quand vous avez des dépendances système spécifiques ou des contraintes de compatibilité avec d’autres conteneurs de votre pile.

Configurer un conteneur PostgreSQL avec les variables essentielles

La configuration d’un conteneur PostgreSQL repose principalement sur des variables d’environnement. C’est l’un des aspects les mieux pensés de l’image officielle. Voici les variables que j’utilise systématiquement dans mes projets :

POSTGRES_PASSWORD est la seule variable obligatoire. Elle définit le mot de passe du superutilisateur. Sans elle, le conteneur refuse de démarrer et vous obtiendrez un message d’erreur explicite. En production, je privilégie toujours l’utilisation de POSTGRES_PASSWORD_FILE qui permet de lire le mot de passe depuis un fichier, compatible avec les Docker Secrets.

POSTGRES_USER permet de définir un utilisateur personnalisé au lieu du postgres par défaut. Si vous la définissez, cet utilisateur disposera des droits de superutilisateur. C’est pratique pour isoler les accès dès le départ.

POSTGRES_DB crée automatiquement une base de données au démarrage. Sans cette variable, une base portant le nom de l’utilisateur sera créée. Je la définis toujours explicitement pour éviter toute ambiguïté dans mes scripts d’initialisation.

La variable POSTGRES_PORT est souvent source de confusion. Elle ne modifie pas le port à l’intérieur du conteneur (qui reste 5432). Pour exposer PostgreSQL sur un port différent de l’hôte, c’est le mapping de ports Docker qu’il faut ajuster : -p 5433:5432 par exemple. Cette distinction entre port interne et port externe est fondamentale dans la gestion des réseaux Docker.

D’autres variables moins connues mais utiles incluent POSTGRES_INITDB_ARGS pour passer des arguments à initdb (comme --encoding=UTF8 --locale=fr_FR.UTF-8) et PGDATA pour modifier l’emplacement du répertoire de données à l’intérieur du conteneur.

docker run -d \
  --name mon-postgres \
  -e POSTGRES_USER=app_user \
  -e POSTGRES_PASSWORD=motdepasse_securise \
  -e POSTGRES_DB=ma_base \
  -p 5432:5432 \
  -v pgdata:/var/lib/postgresql/data \
  postgres:16-alpine

Cette commande crée un conteneur PostgreSQL 16 sur base Alpine, avec un utilisateur personnalisé, une base dédiée et un volume nommé pour la persistance. C’est mon point de départ pour tout nouveau projet.

Comparatif des images PostgreSQL sur Docker Hub

Docker Hub héberge plusieurs images PostgreSQL maintenues par des éditeurs différents. Chacune répond à des besoins spécifiques. J’ai compilé un comparatif basé sur mon expérience concrète avec chacune d’entre elles.

Infrastructure serveur hébergeant des conteneurs PostgreSQL en production
Infrastructure serveur hébergeant des conteneurs PostgreSQL en production

Image Base système Taille approximative Non-root par défaut Cas d’usage principal
postgres (officielle) Debian Bookworm ~250 Mo Non Usage général, développement, production
postgres:alpine Alpine Linux ~80 Mo Non Environnements légers, CI/CD
bitnami/postgresql Debian (Bitnami) ~200 Mo Oui Production sécurisée, Kubernetes
ubuntu/postgres Ubuntu LTS ~300 Mo Non Conformité entreprise Ubuntu
alpine/psql Alpine Linux ~15 Mo Oui Client psql uniquement (pas de serveur)

L’image bitnami/postgresql mérite une attention particulière. Contrairement à l’image officielle, elle s’exécute par défaut avec un utilisateur non-root, ce qui est un avantage considérable en termes de sécurité. Elle propose aussi un système de réplication maître/esclave intégré et des mécanismes de sauvegarde automatisés. Je la recommande pour les déploiements Kubernetes où les contraintes de sécurité sont plus strictes.

L’image alpine/psql est différente des autres : elle ne contient pas de serveur PostgreSQL, uniquement le client psql. C’est un outil de diagnostic ultra-léger que j’utilise régulièrement pour me connecter à des bases distantes sans installer PostgreSQL sur ma machine. Avec ses 15 Mo, elle se télécharge en quelques secondes.

L’image ubuntu/postgres, maintenue par Canonical, cible les organisations qui standardisent leur infrastructure sur Ubuntu. Elle intègre les correctifs de sécurité Ubuntu et suit le cycle de support LTS. Si votre entreprise impose Ubuntu comme socle technique, c’est un choix cohérent, même si la taille est plus importante.

Pour approfondir le comparatif entre ces différentes images, je vous invite à consulter mon article dédié sur le comparatif des images Postgres sur Docker Hub qui détaille les benchmarks de performances.

Déployer PostgreSQL avec Docker Compose

En pratique, je ne déploie quasiment jamais PostgreSQL avec une simple commande docker run. J’utilise systématiquement Docker Compose qui permet de versionner la configuration, de gérer les dépendances entre services et de simplifier les déploiements répétables. Voici un fichier docker-compose.yml que j’utilise comme base dans mes formations :

version: '3.8'

services:
  db:
    image: postgres:16-alpine
    container_name: postgres-app
    restart: unless-stopped
    environment:
      POSTGRES_USER: app_user
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
      POSTGRES_DB: production_db
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./init-scripts:/docker-entrypoint-initdb.d:ro
    networks:
      - backend
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app_user -d production_db"]
      interval: 10s
      timeout: 5s
      retries: 5

secrets:
  db_password:
    file: ./secrets/db_password.txt

volumes:
  pgdata:

networks:
  backend:
    driver: bridge

Plusieurs points importants dans cette configuration. Le healthcheck utilise pg_isready, l’outil natif de PostgreSQL pour vérifier que le serveur accepte les connexions. C’est indispensable quand d’autres services dépendent de la base de données : ils attendront que PostgreSQL soit réellement prêt avant de démarrer.

Le volume init-scripts est monté en lecture seule (:ro) pour éviter que le conteneur ne modifie accidentellement vos scripts d’initialisation. C’est une bonne pratique de sécurité que j’enseigne dans ma formation Docker.

La section secrets évite de stocker le mot de passe en clair dans le fichier Compose. C’est une amélioration majeure par rapport à la variable POSTGRES_PASSWORD en dur, surtout si votre fichier docker-compose.yml est versionné dans Git. Pour comprendre les subtilités de la configuration réseau dans ce type de déploiement, consultez mon guide sur les différences entre net et network dans Docker Compose.

Le paramètre restart: unless-stopped garantit que le conteneur redémarre automatiquement après un crash ou un redémarrage de l’hôte, sauf si vous l’avez arrêté volontairement. En production, c’est un filet de sécurité simple mais efficace.

Sécuriser et optimiser votre image PostgreSQL

Déployer PostgreSQL dans Docker ne dispense pas d’appliquer les bonnes pratiques de sécurité. Voici les mesures que je mets en place systématiquement, que ce soit pour un projet étudiant ou une mise en production.

Configuration d'un fichier Docker Compose pour orchestrer PostgreSQL
Configuration d’un fichier Docker Compose pour orchestrer PostgreSQL

Premièrement, ne jamais utiliser le tag latest. Je l’ai déjà mentionné, mais c’est tellement important que je le répète. Verrouillez la version majeure au minimum (postgres:16), idéalement la version mineure (postgres:16.4). Cela vous protège des mises à jour non maîtrisées qui pourraient introduire des incompatibilités. Pour comprendre l’importance du versionnement des images, lisez mon article sur le versionnement Docker.

Deuxièmement, configurez le fichier pg_hba.conf pour restreindre les connexions. Par défaut, l’image officielle accepte les connexions depuis n’importe quelle adresse IP avec authentification par mot de passe. En production, je monte un fichier pg_hba.conf personnalisé qui limite les connexions aux sous-réseaux Docker connus :

# pg_hba.conf personnalisé
local   all   all                 trust
host    all   all   172.18.0.0/16  scram-sha-256
host    all   all   0.0.0.0/0      reject

Troisièmement, ajustez les paramètres de performance selon votre cas d’usage. Les valeurs par défaut de PostgreSQL sont conservatrices et adaptées à une petite machine. Pour un conteneur avec des ressources dédiées, je modifie au minimum ces paramètres via un fichier postgresql.conf monté en volume ou via des arguments de ligne de commande :

docker run -d \
  --name postgres-optimise \
  -e POSTGRES_PASSWORD=secure_pass \
  postgres:16-alpine \
  -c shared_buffers=256MB \
  -c work_mem=16MB \
  -c maintenance_work_mem=128MB \
  -c max_connections=100

Quatrièmement, surveillez les mises à jour de sécurité. La page officielle de sécurité PostgreSQL publie régulièrement des correctifs. L’image Docker officielle est généralement mise à jour dans les 48 heures suivant la publication d’un correctif de sécurité. Intégrez un processus de mise à jour régulier dans votre pipeline CI/CD.

Enfin, pensez à la sensibilisation de vos équipes à la cybersécurité. Un conteneur PostgreSQL mal configuré reste une porte d’entrée potentielle, même s’il est isolé dans un réseau Docker.

Gérer la persistance et les sauvegardes

La persistance des données est le sujet le plus critique quand on utilise PostgreSQL dans Docker. Un conteneur est éphémère par nature : sans volume, toutes vos données disparaissent à la suppression du conteneur. J’ai vu ce scénario causer des pertes de données en environnement de développement plus souvent que je ne voudrais l’admettre.

Il existe deux approches pour la persistance. Les volumes nommés (pgdata:/var/lib/postgresql/data) sont gérés par Docker et stockés dans /var/lib/docker/volumes/. C’est la solution que je recommande par défaut : Docker gère les permissions, la portabilité et le cycle de vie. Les bind mounts (./data:/var/lib/postgresql/data) lient un répertoire de l’hôte directement au conteneur. C’est utile pour inspecter les fichiers de données, mais les problèmes de permissions sont fréquents, surtout sous Linux.

Pour les sauvegardes, j’utilise pg_dump exécuté depuis un conteneur éphémère qui se connecte au conteneur PostgreSQL via le réseau Docker :

docker exec postgres-app pg_dump -U app_user -F c production_db > backup_$(date +%Y%m%d).dump

Cette commande produit un dump au format custom (-F c) qui est compressé et permet une restauration sélective. Pour les bases volumineuses, pg_basebackup est plus adapté car il effectue une copie physique complète, compatible avec la restauration point-in-time (PITR).

En production, j’automatise ces sauvegardes avec un conteneur dédié qui exécute un script cron. Le stockage des sauvegardes se fait idéalement sur un volume séparé ou directement vers un stockage objet (S3, MinIO). Si vous envisagez de migrer votre infrastructure PostgreSQL vers le cloud, mon guide sur la migration d’infrastructure dans le cloud détaille les étapes clés.

Un point souvent négligé : testez régulièrement vos restaurations. Une sauvegarde qui n’a jamais été testée n’est pas une sauvegarde. Je programme un test de restauration mensuel dans un conteneur temporaire pour vérifier l’intégrité de mes dumps.

Cas pratiques et erreurs fréquentes

Après plusieurs années à accompagner des étudiants et des développeurs sur Docker Hub PostgreSQL, j’ai identifié des erreurs récurrentes que je souhaite vous éviter.

Erreur n°1 : oublier le volume au premier lancement. Vous lancez votre conteneur, vous créez vos tables, vous insérez des données. Puis vous faites docker rm pour recréer le conteneur avec une nouvelle configuration. Toutes vos données ont disparu. La solution : toujours déclarer un volume dès le premier docker run, même en développement.

Erreur n°2 : modifier les scripts d’initialisation après le premier démarrage. Les scripts dans /docker-entrypoint-initdb.d/ ne s’exécutent qu’une seule fois, lors de la création initiale de la base. Si vous modifiez un script et redémarrez le conteneur, rien ne se passe. Il faut supprimer le volume et recréer le conteneur pour que les nouveaux scripts soient pris en compte.

Erreur n°3 : exposer le port 5432 sur 0.0.0.0 en production. La commande -p 5432:5432 expose PostgreSQL sur toutes les interfaces réseau de l’hôte, y compris l’interface publique. En production, limitez l’exposition à l’interface locale (-p 127.0.0.1:5432:5432) ou mieux, n’exposez pas le port du tout et utilisez uniquement le réseau interne Docker Compose.

Erreur n°4 : ignorer les logs du conteneur. PostgreSQL produit des logs détaillés qui sont accessibles via docker logs postgres-app. Ces logs contiennent des informations précieuses sur les erreurs de connexion, les requêtes lentes et les problèmes de configuration. Configurez un niveau de log adapté avec -c log_statement=all en développement et -c log_min_duration_statement=1000 en production pour capturer les requêtes de plus d’une seconde.

Erreur n°5 : négliger la compatibilité des versions lors des mises à jour. PostgreSQL ne supporte pas la mise à jour majeure en place des fichiers de données. Passer de postgres:15 à postgres:16 nécessite un export/import via pg_dump ou l’utilisation de pg_upgrade. C’est une opération planifiée, pas un simple changement de tag dans votre fichier Compose.

Pour ceux qui explorent des alternatives à Docker pour la conteneurisation, mon comparatif Podman vs Docker analyse les différences concrètes entre ces deux outils, y compris pour PostgreSQL.

Si vous souhaitez coupler votre base PostgreSQL avec un outil de monitoring, découvrez comment installer Grafana avec Docker pour visualiser les métriques de performance de votre serveur de base de données.

À retenir

  • Utilisez toujours un tag versionné (ex. postgres:16-alpine) plutôt que latest pour éviter les mises à jour non contrôlées
  • Déclarez un volume nommé dès le premier lancement pour garantir la persistance de vos données
  • Stockez vos mots de passe via Docker Secrets ou POSTGRES_PASSWORD_FILE plutôt qu’en clair dans le fichier Compose
  • Configurez un healthcheck avec pg_isready pour orchestrer correctement le démarrage de vos services
  • Testez vos restaurations de sauvegardes au moins une fois par mois dans un conteneur temporaire

Questions fréquentes


Quelle est la différence entre l’image postgres et l’image bitnami/postgresql sur Docker Hub ?

L’image officielle postgres est maintenue par le projet Docker Library et s’exécute en tant que root par défaut. L’image bitnami/postgresql s’exécute avec un utilisateur non-root, propose des mécanismes de réplication intégrés et suit les conventions Bitnami pour la configuration. En production avec Kubernetes, l’image Bitnami est souvent préférée pour ses propriétés de sécurité renforcées.

Comment choisir entre les tags Alpine et Debian pour l’image PostgreSQL ?

Les tags Alpine produisent des images d’environ 80 Mo contre 250 Mo pour Debian. Choisissez Alpine pour les environnements de développement, les pipelines CI/CD ou quand la taille compte. Préférez Debian si vous avez besoin de bibliothèques système spécifiques, de compatibilité glibc ou si vous rencontrez des problèmes avec musl libc utilisée par Alpine.

Comment persister les données PostgreSQL dans Docker ?

Utilisez un volume Docker nommé en ajoutant l’option -v pgdata:/var/lib/postgresql/data à votre commande docker run, ou déclarez un volume dans la section volumes de votre fichier docker-compose.yml. Les volumes nommés survivent à la suppression et à la recréation des conteneurs, contrairement aux données stockées dans le système de fichiers du conteneur.

Peut-on utiliser Docker Hub PostgreSQL en production ?

Oui, à condition de respecter les bonnes pratiques : verrouiller la version de l’image, configurer les volumes pour la persistance, utiliser Docker Secrets pour les mots de passe, restreindre les accès réseau via pg_hba.conf et mettre en place des sauvegardes automatisées avec pg_dump ou pg_basebackup. De nombreuses entreprises utilisent PostgreSQL conteneurisé en production avec succès.

Comment se connecter à un conteneur PostgreSQL avec le client psql ?

Vous pouvez exécuter psql directement dans le conteneur avec docker exec -it mon-postgres psql -U app_user -d ma_base. Alternativement, utilisez l’image ultra-légère alpine/psql pour vous connecter depuis un conteneur éphémère : docker run --rm -it alpine/psql -h adresse_ip -U app_user -d ma_base. Cette seconde approche est idéale pour le diagnostic sans installer psql sur votre machine.

Comment mettre à jour PostgreSQL dans Docker sans perdre de données ?

Pour une mise à jour mineure (ex. 16.3 vers 16.4), changez simplement le tag et recréez le conteneur : les données sur le volume restent compatibles. Pour une mise à jour majeure (ex. 15 vers 16), exportez d’abord vos données avec pg_dump, mettez à jour l’image, supprimez le volume, recréez le conteneur et importez vos données. Ne tentez jamais de réutiliser un volume de données avec une version majeure différente de PostgreSQL.


Lucie Moreau
Lucie Moreau

Formatrice IT indépendante depuis 2016, ancienne étudiante BTS SIO SLAM. 6 ans d'expérience en entreprise.

Lucie Moreau

Formatrice IT indépendante depuis 2016, ancienne étudiante BTS SIO SLAM. 6 ans d'expérience en entreprise.