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
postgresse 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