Docker pour les devs - 20 - Bases de donnees dans Docker

PostgreSQL, Redis et pgAdmin dans Docker. Volumes persistants, configuration custom et connexion entre conteneurs.

  1. 01 Docker pour les devs - 00 - Pourquoi Docker change tout
  2. 02 Docker pour les devs - 01 - Containers vs VMs
  3. 03 Docker pour les devs - 02 - L'architecture de Docker
  4. 04 Docker pour les devs - 03 - Docker Desktop, Engine et alternatives
  5. 05 Docker pour les devs - 04 - Écrire un Dockerfile
  6. 06 Docker pour les devs - 05 - Layers et cache
  7. 07 Docker pour les devs - 06 - Le .dockerignore
  8. 08 Docker pour les devs - 07 - Multi-stage builds
  9. 09 Docker pour les devs - 08 - Choisir son image de base
  10. 10 Docker pour les devs - 09 - Docker Compose, les bases
  11. 11 Docker pour les devs - 10 - Docker Compose avance
  12. 12 Docker pour les devs - 11 - Networking Docker, les bases
  13. 13 Docker pour les devs - 12 - Networking Docker avance
  14. 14 Docker pour les devs - 13 - Volumes et persistance
  15. 15 Docker pour les devs - 14 - Variables d'environnement et secrets
  16. 16 Docker pour les devs - 15 - Permissions et utilisateurs
  17. 17 Docker pour les devs - 16 - Docker et monorepo
  18. 18 Docker pour les devs - 17 - Dev vs Prod
  19. 19 Docker pour les devs - 18 - ENTRYPOINT, CMD et scripts d'initialisation
  20. 20 Docker pour les devs - 19 - Debugger ses conteneurs
  21. 21 Docker pour les devs - 20 - Bases de donnees dans Docker
  22. 22 Docker pour les devs - 21 - Sauvegardes et restauration
  23. 23 Docker pour les devs - 22 - Conteneuriser un frontend
  24. 24 Docker pour les devs - 23 - Sécurité des conteneurs
  25. 25 Docker pour les devs - 24 - Optimisation des images
  26. 26 Docker pour les devs - 25 - Builds multi-platform
  27. 27 Docker pour les devs - 26 - Limiter les ressources de tes conteneurs
  28. 28 Docker pour les devs - 27 - Gerer les logs comme un adulte
  29. 29 Docker pour les devs - 28 - Healthchecks et restart policies
  30. 30 Docker pour les devs - 29 - Nettoyer Docker avant qu'il mange ton disque
  31. 31 Docker pour les devs - 30 - Registries et stratégie de tags
  32. 32 Docker pour les devs - 31 - Docker en CI/CD
  33. 33 Docker pour les devs - 32 - Au-dela de Compose
  34. 34 Docker pour les devs - 33 - Glossaire Docker de A a Z

20 - Bases de donnees dans Docker

Ce que tu vas apprendre

  • Lancer PostgreSQL avec l'image officielle et les bonnes variables
  • Persister les donnees avec des named volumes
  • Ajouter une configuration PostgreSQL custom
  • Lancer Redis dans Docker
  • Connecter ton app a la base (DNS Docker)
  • Installer pgAdmin pour gerer ta base visuellement

Prerequisites

Savoir utiliser Docker Compose (article précédent sur le debug). Connaitre les bases de SQL. Avoir Docker et Docker Compose installes.


La première chose que je dockerise sur un projet, c'est la base de donnees. Fini les installations système de PostgreSQL qui polluent ta machine, les conflits de versions entre projets et les "ca marchait sur mon poste". En deux minutes, tu as une base propre et isolee.

PostgreSQL : le setup de base

yamlservices:
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: myapp
      POSTGRES_PASSWORD: secret123
      POSTGRES_DB: myapp_dev
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

Trois variables et c'est pret. POSTGRES_USER créé l'utilisateur, POSTGRES_PASSWORD definit son mot de passe, POSTGRES_DB créé la base au premier démarrage. Si tu ne mets que POSTGRES_PASSWORD, l'utilisateur par défaut est postgres.

Le volume pgdata est un named volume. Docker le gere, les donnees survivent aux redemarrages et aux recreations du conteneur. Sans ce volume, tu perds tout a chaque docker compose down.

Scripts d'initialisation

L'image officielle PostgreSQL exécuté automatiquement les fichiers .sql et .sh places dans /docker-entrypoint-initdb.d/ au premier démarrage (et seulement au premier, quand le volume est vide).

yamlservices:
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: myapp
      POSTGRES_PASSWORD: secret123
      POSTGRES_DB: myapp_dev
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./init-scripts:/docker-entrypoint-initdb.d
sql-- init-scripts/01-extensions.sql
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
sql-- init-scripts/02-seed.sql
INSERT INTO users (name, email) VALUES
  ('Admin', 'admin@example.com'),
  ('Test', 'test@example.com');

Les fichiers s'executent dans l'ordre alphabetique, d'ou les prefixes numériques. C'est pratique pour créer des extensions, des tables ou des donnees de test.

Configuration PostgreSQL custom

Le postgresql.conf par défaut est conservateur. Pour le dev, tu peux le tweaker :

conf# custom-postgres.conf
listen_addresses = '*'
max_connections = 100
shared_buffers = 256MB
work_mem = 16MB
log_statement = 'all'
log_duration = on

Le log_statement = 'all' affiche toutes les requêtes dans les logs. Genial pour le dev, a ne surtout pas activer en prod.

yamlservices:
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: myapp
      POSTGRES_PASSWORD: secret123
      POSTGRES_DB: myapp_dev
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./custom-postgres.conf:/etc/postgresql/postgresql.conf
    command: ["postgres", "-c", "config_file=/etc/postgresql/postgresql.conf"]

Sur paltemps.fr, j'utilise la config par défaut en dev et une config durcie en prod. La séparation dev/prod qu'on a vue dans l'article précédent s'applique aussi a la base.

Redis : encore plus simple

yamlservices:
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redisdata:/data
    command: ["redis-server", "--appendonly", "yes"]

volumes:
  redisdata:

Le --appendonly yes active la persistance AOF. Sans ca, Redis garde tout en mémoire et tu perds les donnees au redemarrage. Pour du cache pur, tu peux le laisser sans persistance.

Si tu veux un mot de passe :

yamlservices:
  redis:
    image: redis:7-alpine
    command: ["redis-server", "--appendonly", "yes", "--requirepass", "redis_secret"]

Connexion depuis l'app

Dans Docker Compose, chaque service est accessible par son nom. Pas besoin d'adresses IP :

yamlservices:
  app:
    build: .
    environment:
      DATABASE_URL: postgres://myapp:secret123@db:5432/myapp_dev
      REDIS_URL: redis://:redis_secret@redis:6379
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: myapp
      POSTGRES_PASSWORD: secret123
      POSTGRES_DB: myapp_dev
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U myapp"]
      interval: 5s
      timeout: 5s
      retries: 5
    volumes:
      - pgdata:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    command: ["redis-server", "--appendonly", "yes"]
    volumes:
      - redisdata:/data

Le db dans l'URL @db:5432 correspond au nom du service. Docker resout ce DNS automatiquement sur le réseau interne. Le healthcheck sur PostgreSQL avec pg_isready garantit que la base accepte les connexions avant de lancer l'app.

pgAdmin dans Docker

Pour gerer ta base avec une interface graphique :

yamlservices:
  pgadmin:
    image: dpage/pgadmin4:latest
    environment:
      PGADMIN_DEFAULT_EMAIL: admin@local.dev
      PGADMIN_DEFAULT_PASSWORD: admin
    ports:
      - "5050:80"
    depends_on:
      - db

Tu accedes a pgAdmin sur http://localhost:5050, tu te connectes avec les identifiants définis, puis tu ajoutes un serveur avec le host db (pas localhost, parce que pgAdmin est dans le réseau Docker).

Je n'utilise pgAdmin que quand j'ai besoin de visualiser des donnees. Pour les requêtes quotidiennes, un client SQL en ligne de commande ou un plugin VSCode fait le job.

Le compose complet

yamlservices:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgres://myapp:secret123@db:5432/myapp_dev
      REDIS_URL: redis://redis:6379
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: myapp
      POSTGRES_PASSWORD: secret123
      POSTGRES_DB: myapp_dev
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U myapp"]
      interval: 5s
      timeout: 5s
      retries: 5
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./init-scripts:/docker-entrypoint-initdb.d

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redisdata:/data

volumes:
  pgdata:
  redisdata:

Un docker compose up et tu as ton app, ta base et ton cache. C'est ca la vraie valeur de Docker pour le dev quotidien. On verra dans le prochain article comment sauvegarder et restaurer ces donnees.

Résumé

  • L'image officielle postgres se configure avec trois variables d'environnement.
  • Les named volumes persistent les donnees entre les redemarrages.
  • Les scripts dans /docker-entrypoint-initdb.d/ s'executent au premier lancement.
  • Les services Docker Compose se trouvent par leur nom DNS.
  • Le healthcheck pg_isready évité de démarrer l'app avant que la base soit prete.
  • pgAdmin s'ajoute en un service pour gerer la base visuellement.

Article précédent : Docker 19 - Debug Article suivant : Docker 21 - Backup

Sources

Réservez un audit gratuit de 30 minutes. Je vous montre concrètement ce qu'on peut automatiser.