Infrastructure : Déploiement de Ghost via Docker Compose

Infrastructure : Déploiement de Ghost via Docker Compose

La fiabilité d'une plateforme de contenu repose sur la simplicité et la reproductibilité de son environnement. Chez MADSAAS, nous avons fait le choix d'orchestrer notre instance Ghost via Docker Compose pour garantir une mise en production rapide, maintenable et sécurisée.

Déployer Ghost via Docker Compose n'est pas seulement une question de commodité, c'est une stratégie d'ingénierie moderne. Cela nous permet d'isoler les services, de gérer la persistance des données de manière déclarative et de garantir la cohérence entre nos environnements de développement et de production.

Notre approche Docker Compose

Nous utilisons une stack complète comprenant Ghost (Alpine Linux) et MySQL 8.0, orchestrés via un fichier unique qui définit l'ensemble de notre infrastructure applicative.

Voici le docker-compose.yml que nous utilisons pour propulser ce site :

version: "3.8"

services:
  ghost:
    image: ghost:5-alpine
    container_name: ${DOCKER_APP_NAME}
    restart: unless-stopped
    ports:
      - "2371:2368"
    environment:
      url: ${GHOST_URL}
      database__client: mysql
      database__connection__host: ${MYSQL_HOST}
      database__connection__user: ${MYSQL_USER}
      database__connection__password: ${MYSQL_PASSWORD}
      database__connection__database: ${MYSQL_DATABASE}
      NODE_ENV: ${NODE_ENV}
    volumes:
      # Theme mount — hot reload on restart
      - ./madsaas-theme:/var/lib/ghost/content/themes/madsaas-theme
      # Persist content (images, data, etc.)
      - ghost_content_madsaas:/var/lib/ghost/content
    depends_on:
      db:
        condition: service_healthy

  db:
    image: mysql:8.0
    container_name: ${DOCKER_DB_NAME}
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
      - ghost_db_madsaas:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  ghost_content_madsaas:
  ghost_db_madsaas:

Configuration des variables d'environnement

Pour sécuriser et centraliser notre configuration, nous utilisons un fichier .env à la racine du projet :

# Application
DOCKER_APP_NAME=ghost-madsaas
DOCKER_DB_NAME=ghost-db-madsaas
NODE_ENV=production

# Ghost Configuration
GHOST_URL=https://votre-domaine.fr

# MySQL Configuration
MYSQL_HOST=db
MYSQL_DATABASE=ghost_prod
MYSQL_USER=ghost_user
MYSQL_PASSWORD=VotreMotDePasseSecurise123!
MYSQL_ROOT_PASSWORD=VotreRootPasswordSecurise456!

Pourquoi cette architecture ?

Séparation des responsabilités

Chaque service a un rôle bien défini. Ghost gère l'application web tandis que MySQL assure la persistance des données. Cette séparation permet de scaler ou de maintenir chaque composant indépendamment.

Gestion intelligente des volumes

Nous utilisons deux types de volumes pour optimiser flexibilité et performance :

Volume nommé (ghost_content_madsaas) pour la persistance générale du contenu. Docker gère automatiquement l'emplacement et les permissions, garantissant une portabilité maximale entre environnements.

Bind mount (./madsaas-theme) pour notre thème personnalisé. Cette approche permet un développement en temps réel : toute modification du thème est immédiatement disponible après redémarrage du conteneur, sans reconstruction d'image.

Health checks et dépendances

La directive depends_on avec condition service_healthy garantit que Ghost ne démarre qu'une fois MySQL opérationnel. Le healthcheck MySQL vérifie activement la disponibilité de la base toutes les 10 secondes, éliminant les erreurs de connexion au démarrage.

Sécurité par l'environnement

Toutes les informations sensibles sont externalisées dans le fichier .env, jamais versionnées dans Git. En production, ces variables sont injectées via le système de secrets de notre orchestrateur ou via des variables d'environnement système.

Politique de redémarrage

La directive restart: unless-stopped assure la résilience : en cas de crash applicatif ou de redémarrage serveur, les conteneurs redémarrent automatiquement, garantissant une disponibilité maximale sans intervention manuelle.

Déploiement et maintenance

Le déploiement devient trivial avec cette approche :

# Premier déploiement
docker compose up -d

# Mise à jour de Ghost
docker compose pull ghost
docker compose up -d --no-deps ghost

# Consultation des logs
docker compose logs -f ghost

# Backup de la base de données
docker compose exec db mysqldump -u root -p${MYSQL_ROOT_PASSWORD} ${MYSQL_DATABASE} > backup.sql

Scalabilité et reverse-proxy

En production, ce stack est couplé à Traefik ou Nginx comme reverse-proxy, gérant nativement le SSL via Let's Encrypt, la compression Gzip et le load balancing si nécessaire. Le port 2371 n'est alors accessible que depuis le réseau interne Docker.

Cette rigueur dans notre propre infrastructure est la même que celle que nous appliquons aux projets SaaS de nos clients : reproductible, maintenable et évolutive.