Docker-compose avec PostgreSQL + Adminer + Traefik (reverse proxy)

Cet article montre comment mettre en place un docker-compose minimal qui réunit : PostgreSQL (base de données), Adminer (interface web de gestion) et surtout Traefik (reverse proxy moderne) pour exposer proprement vos services et préparer une montée en production sereine (domaines, HTTPS, middlewares).

Pourquoi Traefik ?

Découverte automatique : Traefik lit les labels Docker et crée les routes à la volée (pas de conf Nginx à maintenir).
Dès qu’un service démarre avec des labels (traefik.enable=true, traefik.http.routers…), Traefik crée dynamiquement la route correspondante.

HTTPS automatique : Traefik gère Let’s Encrypt en natif via ACME.

  • Il suffit de fournir l’email et le domaine (DOMAIN=example.com dans le .env), et Traefik se charge de :
    • demander le certificat SSL,
    • le stocker dans letsencrypt/acme.json,
    • le renouveler automatiquement avant expiration.

👉 Résultat : vous avez du HTTPS gratuit, renouvelé sans effort, là où avec Nginx vous devriez installer certbot, configurer les certificats et gérer les cron jobs.
👉 En local : vous pouvez rester en HTTP (*.localhost), mais en prod vous avez directement un HTTPS prêt à l’emploi.

C’est un middlewares puissants : redirection HTTP→HTTPS, authentification basique, rate-limit, en-têtes de sécurité…

  • Traefik ne fait pas que du routage, il ajoute une couche de middlewares pour sécuriser et contrôler le trafic :
    • Redirection HTTP → HTTPS (force le chiffrement).
    • Authentification basique (protège un dashboard ou une app sensible).
    • Rate limiting (limiter le nombre de requêtes par IP, utile contre les abus).
    • Ajout d’en-têtes de sécurité (Strict-Transport-Security, X-Frame-Options, etc.).

  • Il propose un dashboard : Interface web (http://traefik.tondomaine) qui affiche en temps réel :
    • les routes configurées,
    • les services accessibles,
    • l’état des certificats SSL. Très utile pour déboguer rapidement.

Il supporte un empilement de projets : un même proxy pour plusieurs applis (FastAPI, Django, etc.) grâce à un réseau partagé.

Prérequis

Docker et Docker Compose v2 installés.

Un nom de domaine si vous visez le HTTPS (ex. example.com). Pour un usage local, on peut rester en HTTP via *.localhost.

Variables d’environnement (.env)

Créez un fichier .env à la racine pour centraliser les secrets et le domaine.

# Nom de domaine principal (ex: exemple.com ou localhost en dev)

DOMAIN=example.com


# Adresse email pour l'enregistrement Let's Encrypt (obligatoire pour générer un certificat SSL)

ACME_EMAIL=votre_email@example.com


# Sécurité : utilisateur(s) autorisé(s) pour accéder au dashboard Traefik

# Générer un mot de passe hashé avec :

# htpasswd -nbB admin "motdepasse" | sed -e 's/\$/\$\$/g'
TRAEFIKUSERS=admin:2y05$hashABRÉGÉDExxx...

# Nom de la base

POSTGRES_DB=appdb


# Identifiants de connexion

POSTGRES_USER=appuser

POSTGRES_PASSWORD=mot_de_passe_sûr

  • 👉 Explications :
    • DOMAIN : utilisé par tous les services pour construire les règles de routage (adminer.${DOMAIN}traefik.${DOMAIN}, etc.).
    • ACME_EMAIL : permet à Let’s Encrypt de t’envoyer des alertes en cas de problème de certificat.
    • TRAEFIK_USERS : protège le dashboard Traefik avec une authentification basique.
    • POSTGRES_DB : nom de ta base par défaut.
    • POSTGRES_USER / POSTGRES_PASSWORD : utilisés à la fois par PostgreSQL et par Adminer pour se connecter.

Le docker-compose.yml

Voici un fichier complet : Traefik (reverse proxy), PostgreSQL et Adminer, avec des labels pour le routage.

Dockerfile
version: "3.9"

services:
  traefik:
    image: traefik:v3.0
    container_name: traefik
    command:

      - --api.dashboard=true
      - --api.insecure=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
# ACME / Let's Encrypt (HTTP challenge)
      - --certificatesresolvers.letsencrypt.acme.email={ACME_EMAIL} 
      - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json 
      - --certificatesresolvers.letsencrypt.acme.httpchallenge=true 
      - --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web 
    ports: 
      - "80:80" 
      - "443:443" 
    volumes: 
      - /var/run/docker.sock:/var/run/docker.sock:ro 
      - ./letsencrypt:/letsencrypt 
    networks: 
      - web 
    labels: 
    - "traefik.enable=true" 
    # Dashboard Traefik (protégé par auth basique) 
    - "traefik.http.routers.traefik.rule=Host(traefik.{DOMAIN})"
    - "traefik.http.routers.traefik.entrypoints=web"
    - "traefik.http.routers.traefik.service=api@internal"
    - "traefik.http.middlewares.dashboard-auth.basicauth.users=TRAEFIKUSERS""traefik.http.routers.traefik.middlewares=dashboard−auth"
  db:
    image:postgres:16
    containername:postgres
    environment:
      −POSTGRESDB={POSTGRES_DB}
      - POSTGRES_USER=POSTGRESUSER
      − POSTGRESPASSWORD={POSTGRES_PASSWORD}
    volumes:

      - dbdata:/var/lib/postgresql/data
    networks:
      - internal

  adminer:
    image: adminer:latest
    container_name: adminer
    depends_on:
      - db
    networks:
      - internal
      - web
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.adminer.rule=Host(adminer.${DOMAIN})"
      - "traefik.http.routers.adminer.entrypoints=web"
      # Port exposé par le conteneur Adminer
      - "traefik.http.services.adminer.loadbalancer.server.port=8080"
      # (Optionnel en prod HTTPS)
      #   - "traefik.http.routers.adminer.tls=true"
      #   - "traefik.http.routers.adminer.tls.certresolver=letsencrypt"


volumes:
  dbdata:
networks:
  web:
    external: true
# réseau partagé pour que Traefik voie d'autres stacks
  internal:
    internal: true 
# réseau privé DB & services

Démarrage

Bash
docker compose up -d

Ensuite :

  • Accédez à http://traefik.<votre domaine> pour le dashboard (auth basique requise).
  • Accédez à http://adminer.<votre domaine> pour Adminer.

Connexion Adminer à PostgreSQL

  • Système : PostgreSQL
  • Serveur : db (nom du service Docker, car Adminer et la DB partagent le réseau internal)
  • Utilisateur : ${POSTGRES_USER}
  • Mot de passe : ${POSTGRES_PASSWORD}
  • Base : ${POSTGRES_DB}

Zoom sur Traefik : labels & routage

Le cœur de Traefik dans un contexte Docker, ce sont les labels posés sur chaque service.
Ils définissent  et comment exposer le service.
Exemple minimal utilisé ci-dessus pour Adminer :

Dockerfile
labels:   

  - "traefik.enable=true" 

  - "traefik.http.routers.adminer.rule=Host(`adminer.${DOMAIN}`)" 

  - "traefik.http.routers.adminer.entrypoints=web" 

  - "traefik.http.services.adminer.loadbalancer.server.port=8080"

Avec le HTTPS automatique (Let’s Encrypt), on ajoute :

Dockerfile
  - "traefik.http.routers.adminer.tls=true" 

  - "traefik.http.routers.adminer.tls.certresolver=letsencrypt"

On peut aussi empiler des middlewares (auth, redirections, en-têtes de sécurité) :

Dockerfile
 - "traefik.http.middlewares.hsts.headers.stsSeconds=31536000" 

 - "traefik.http.middlewares.hsts.headers.stsIncludeSubdomains=true" 

 - "traefik.http.routers.adminer.middlewares=hsts"

Ajouter facilement une autre application (ex. FastAPI)

Une fois Traefik en place, exposer une nouvelle app revient à lui ajouter des labels :

Dockerfile
app: 
  image: tiangolo/uvicorn-gunicorn-fastapi:python3.11 
  environment: 
   - MODULE_NAME=main 
  networks: - web
  labels: 
   - "traefik.enable=true" 
   - "traefik.http.routers.app.rule=Host(`api.${DOMAIN}`)" 
   - "traefik.http.routers.app.entrypoints=web" 
   - "traefik.http.services.app.loadbalancer.server.port=80" 
   # HTTPS en prod : 
   #- "traefik.http.routers.app.tls=true" 
   #- "traefik.http.routers.app.tls.certresolver=letsencrypt"

Bonnes pratiques & sécurité

  • Secrets : ne commitez pas .env ; utilisez un coffre de secrets ou des variables d’environnement CI/CD.
  • Traefik dashboard : gardez l’auth basique activée ou désactivez le dashboard en prod (--api.dashboard=false).
  • HTTPS : en production, activez websecure et Let’s Encrypt, et forcez la redirection HTTP→HTTPS.
  • Réseaux : isolez la base sur un réseau internal (comme ci-dessus), exposez uniquement via Traefik.
  • Mises à jour : mettez à jour régulièrement les images (postgresadminertraefik).

Dépannage rapide

  • 404 Traefik : vérifiez la règle Host() et le DNS/hosts. Assurez-vous que le service a traefik.enable=true.
  • Certificats : Let’s Encrypt nécessite un domaine public accessible en HTTP (port 80 ouvert).
  • Adminer n’atteint pas la DB : vérifiez que les services partagent bien le réseau internal et que l’hôte est db.

Remarque

Si vous voulez que votre domaine (par exemple `adminer.localhost` ou autre) fonctionne en local, il faut ajouter une entrée dans votre fichier `hosts` afin qu’il pointe vers `127.0.0.1`.

1. Ouvrez un terminal et éditez le fichier :

Bash
   sudo nano /etc/hosts

2. Ajoute :

127.0.0.1 adminer.localhost

3. Sauvegarde (`Ctrl+O` puis `Ctrl+X`).

à consulter sur : http://adminer.localhost

Conclusion

Traefik simplifie énormément l’exposition de vos services Docker : un reverse proxy orienté labels, prêt pour la production avec HTTPS automatique et des middlewares utiles.
Associé à PostgreSQL et Adminer, vous obtenez un socle solide pour vos projets data et web, que vous pourrez étendre en quelques lignes pour héberger d’autres applications.

Laisser un commentaire

Your email address will not be published. Required fields are marked *.

*
*