Migration d'infrastructure WalidLab đ§
Migration de l'infrastructure de mon serveur depuis Docker + Traefik vers Dokploy
Migration d'infrastructure : Docker + Traefik vers Dokploy
Introduction
AprÚs plusieurs mois à gérer manuellement mon infrastructure Docker avec Traefik, j'ai décidé de franchir le pas et de migrer vers Dokploy, une plateforme d'orchestration self-hosted qui promet de simplifier drastiquement les déploiements tout en conservant le contrÎle total de l'infrastructure.
Cet article détaille cette migration complÚte, les choix architecturaux effectués, et le retour sur investissement concret d'une telle transition.
Le contexte initial
Mon infrastructure reposait sur une stack classique mais fonctionnelle :
- Docker pour la conteneurisation
- Traefik comme reverse proxy et gestionnaire SSL
- Docker Registry privé pour les images custom
- Des fichiers
docker-compose.ymldispersés sur le serveur - Déploiements manuels via SSH et
git pull
Cette approche fonctionnait, mais présentait plusieurs limitations :
- Chaque déploiement nécessitait une connexion SSH manuelle
- La gestion des labels Traefik devenait verbeuse et répétitive
- Aucun systĂšme de rollback simple en cas d'erreur
- Absence de centralisation pour la gestion des variables d'environnement
- Pas d'intégration CI/CD native
Pourquoi Dokploy ?
Dokploy se positionne comme une alternative self-hosted à des solutions comme Vercel ou Netlify, mais pour l'ensemble de la stack applicative. Les promesses sont alléchantes :
- Interface web moderne pour gérer l'ensemble de l'infrastructure
- Déploiement continu automatique depuis Git (GitHub, GitLab, Gitea)
- Traefik intégré et pré-configuré
- Gestion SSL automatisée via Let's Encrypt
- Support natif de Docker Compose
- Registry Docker intégré
- Logs et monitoring centralisés
L'aspect self-hosted était crucial : je souhaitais conserver le contrÎle total de mes données et de mon infrastructure, sans dépendre d'un service tiers.
Architecture de la solution
Infrastructure physique
L'ensemble de l'infrastructure tourne sur un VPS unique derriĂšre Cloudflare :
Internet
â
Cloudflare (Proxy + CDN + WAF)
â
VPS (Dokploy + Applications)
â
dokploy-network (réseau Docker privé)
Couche de sécurité
J'ai mis en place une architecture en couches pour la sécurité :
Interface d'administration (Dokploy UI)
- Accessible uniquement via VPN (ZeroTier)
- Aucune exposition publique de l'interface
- Authentication forte avec mots de passe complexes
Webhooks Git
- Exposés publiquement mais authentifiés par token
- Configuration Traefik en
PathPrefixpour isoler uniquement/api/deploy/webhook/* - Rate limiting appliqué par Traefik
Applications
- Exposition publique via domaines dédiés
- SSL/TLS automatique avec Let's Encrypt
- Headers de sécurité configurés (HSTS, CSP, etc.)
Cloudflare Workers pour la résilience
J'ai implémenté deux Workers Cloudflare pour gérer intelligemment le trafic :
Worker Maintenance (temporaire)
Pendant la phase de migration, un Worker gÚre trois scénarios :
- Applications dĂ©jĂ migrĂ©es â passthrough vers le serveur
- Applications en cours de migration â page de maintenance Ă©lĂ©gante
- Domaines non configurĂ©s â page 404 personnalisĂ©e
const migratedApps = ['dokploy.walidlab.dev', 'app1.walidlab.dev'];
const configuredApps = ['app2.walidlab.dev', 'app3.walidlab.dev'];
if (migratedApps.includes(url.hostname)) {
return fetch(request); // Passthrough
}
if (configuredApps.includes(url.hostname)) {
return new Response(maintenanceHTML, ...); // Maintenance
}
return new Response(error404HTML, ...); // 404
Cette approche permet une migration progressive sans interruption de service perceptible pour les utilisateurs.
Worker 404 permanent
Avec un wildcard DNS (*.walidlab.dev), tous les sous-domaines pointent vers mon serveur. Le Worker 404 filtre en amont les requĂȘtes vers des domaines non configurĂ©s, rĂ©duisant la charge sur le serveur et amĂ©liorant la sĂ©curitĂ© en Ă©vitant les scans automatisĂ©s.
Avantage collatéral : mon serveur ne voit jamais le trafic malveillant ou les tentatives de scan de domaines aléatoires.
Le protocole ACME et Let's Encrypt : comprendre le fonctionnement
La migration a été l'occasion d'approfondir ma compréhension du protocole ACME (Automatic Certificate Management Environment) utilisé par Let's Encrypt.
Le challenge HTTP-01 en détail
Contrairement à une idée reçue, le challenge HTTP n'est pas une simple validation passive. Voici le flow exact :
Génération locale de la paire de clés : Traefik génÚre la clé privée du certificat en local. Cette clé ne quitte jamais le serveur.
Création d'une demande : Un CSR (Certificate Signing Request) est créé, contenant la clé publique et les informations du domaine.
Authentification ACME : Traefik s'authentifie auprÚs de Let's Encrypt via une clé de compte ACME dédiée, distincte de la clé du certificat.
Challenge : Let's Encrypt génÚre un token aléatoire et demande à Traefik de l'exposer sur
http://domain/.well-known/acme-challenge/TOKENPolling actif : Traefik notifie Let's Encrypt que le challenge est prĂȘt. Ce n'est pas Let's Encrypt qui dĂ©cide quand vĂ©rifier, mais Traefik qui signale sa disponibilitĂ©.
Validation : Let's Encrypt effectue une requĂȘte HTTP depuis ses serveurs pour vĂ©rifier la prĂ©sence du token.
Ămission : Si la validation rĂ©ussit, Let's Encrypt signe le certificat avec sa propre CA et le retourne Ă Traefik.
Stockage : Le certificat est stocké dans
acme.jsonavec la clé privée.
Un point crucial : la clé privée ne transite jamais sur le réseau. Seul le certificat public (signé) est transmis par Let's Encrypt.
Renouvellement automatique
Traefik vĂ©rifie quotidiennement l'expiration des certificats. Ă J-30, il relance automatiquement le processus de renouvellement avec le mĂȘme mĂ©canisme, assurant une continuitĂ© de service sans intervention manuelle.
Migration : méthodologie et défis
Préparation
Avant toute migration, j'ai établi un inventaire complet :
- 13 applications Ă migrer
- 2 bases de données partagées (MongoDB et MariaDB)
- Multiples services interconnectés (architecture microservices)
- Volumes Docker existants à préserver
Approche progressive
J'ai opté pour une migration progressive application par application :
- Application pilote : Migration d'une application non critique pour valider le processus
- Configuration des services partagés : Déploiement des bases de données en tant que services indépendants
- Migration des services principaux : API, frontends, workers
- Tests de communication inter-services : Validation du routage réseau
- Finalisation : Migration des services annexes
Défis rencontrés
Communication inter-conteneurs en Docker Swarm
Dokploy utilise Docker Swarm en sous-couche. Les conteneurs ont des noms complexes incluant des suffixes dynamiques (ex: app.1.h1vzkys2lq01g0icrjnsj37jw), mais Docker Swarm maintient des alias DNS stables basés sur le nom du service.
Leçon apprise : toujours référencer les services par leur nom simple, pas par le nom complet du conteneur.
Variables d'environnement au build time
Avec Vite.js, les variables d'environnement doivent ĂȘtre disponibles au moment du build, pas au runtime. La solution avec Dokploy :
ARG VITE_API_URL
ENV VITE_API_URL=$VITE_API_URL
RUN npm run build
Dokploy transforme automatiquement les variables d'environnement de l'UI en --build-arg lors du build Docker.
Debugging d'une erreur 502 mystérieuse
L'erreur la plus chronophage concernait des 502 aléatoires sur certains endpoints. AprÚs élimination systématique de toutes les hypothÚses (Traefik, DNS, CORS, SSL), l'analyse des logs Traefik a révélé :
"OriginStatus": 502,
"Duration": 45000000
Le 502 provenait de l'API elle-mĂȘme, qui effectuait un fetch vers un autre microservice avec une variable d'environnement mal configurĂ©e. Le timeout de 45 secondes correspondait au timeout par dĂ©faut de Node.js.
Solution : configuration correcte des noms de services Docker Swarm dans les variables d'environnement.
Retour sur investissement
Gains quantifiables
Temps de déploiement
- Avant : ~5 minutes par application (SSH, git pull, docker-compose, vérifications)
- AprĂšs : 0 minute (automatique sur git push)
- ROI : 100% du temps de déploiement économisé
Gestion des certificats SSL
- Avant : Vérifications manuelles périodiques, renouvellements parfois oubliés
- AprÚs : ComplÚtement automatisé avec monitoring intégré
- ROI : Ălimination du risque d'expiration de certificat
Rollback en cas d'erreur
- Avant : git revert + rebuild + redéploiement manuel (~10-15 minutes)
- AprĂšs : 1 clic dans l'interface Dokploy (~30 secondes)
- ROI : Réduction drastique du MTTR (Mean Time To Recovery)
Gains qualitatifs
Réduction de la charge cognitive
- Plus besoin de mémoriser les commandes Docker
- Plus besoin de connaĂźtre l'emplacement exact des compose files
- Interface unifiée pour tous les services
Amélioration de la collaboration
- Possibilité d'embarquer des personnes non-techniques sur les déploiements
- Logs centralisés et accessibles sans SSH
- Historique des déploiements avec possibilité de rollback
Sécurité renforcée
- Interface d'administration non exposée publiquement
- Webhooks avec authentification forte
- Filtrage du trafic malveillant en amont via Cloudflare Workers
Coûts
Temps de migration
- Setup initial : ~2 heures
- Migration de 13 applications : ~4 heures
- Debug et optimisations : ~2 heures
- Total : ~8 heures sur un weekend
Courbe d'apprentissage
- Compréhension de l'architecture Dokploy : ~1 heure
- Maßtrise des spécificités Docker Swarm : ~1 heure
- Total : ~2 heures
Maintenance continue
- Avant : ~2 heures par semaine (déploiements, vérifications, corrections)
- AprĂšs : ~15 minutes par semaine (surveillance, mise Ă jour Dokploy)
- Ăconomie : ~1h45 par semaine, soit ~91 heures par an
Architecture finale
Stack technique
âââââââââââââââââââââââââââââââââââââââââââ
â Cloudflare (Edge) â
â ââ Workers (Maintenance + 404) â
â ââ WAF + DDoS Protection â
â ââ CDN + Cache â
ââââââââââââââŹâââââââââââââââââââââââââââââ
â
âŒ
âââââââââââââââââââââââââââââââââââââââââââ
â VPS Infrastructure â
â â
â âââââââââââââââââââââââââââââââââââ â
â â Dokploy (Management Layer) â â
â â ââ UI (ZeroTier only) â â
â â ââ Webhooks (public, auth) â â
â â ââ Docker Registry â â
â âââââââââââââââââââââââââââââââââââ â
â â
â âââââââââââââââââââââââââââââââââââ â
â â Traefik (Reverse Proxy) â â
â â ââ SSL/TLS (Let's Encrypt) â â
â â ââ Routing â â
â â ââ Middlewares â â
â âââââââââââââââââââââââââââââââââââ â
â â
â âââââââââââââââââââââââââââââââââââ â
â â Applications â â
â â ââ APIs (Node.js, Python) â â
â â ââ Frontends (React, Vue) â â
â â ââ Workers (Background jobs) â â
â âââââââââââââââââââââââââââââââââââ â
â â
â âââââââââââââââââââââââââââââââââââ â
â â Data Layer â â
â â ââ MongoDB (shared) â â
â â ââ MariaDB (shared) â â
â â ââ Redis (caching) â â
â âââââââââââââââââââââââââââââââââââ â
â â
â Network: dokploy-network (overlay) â
âââââââââââââââââââââââââââââââââââââââââââ
Patterns de communication
Inter-services
Les services communiquent via le réseau Docker overlay dokploy-network en utilisant les noms de services comme hostnames. Docker Swarm maintient la résolution DNS automatiquement.
// Configuration d'un service
const API_URL = process.env.API_URL; // http://service-name:port
Base de données partagées
Les bases de données sont déployées comme services indépendants avec des volumes persistants. Chaque application configure sa propre base de données sur l'instance partagée.
# Application 1
MONGODB_URI: mongodb://shared-mongodb:27017/app1_db
# Application 2
MONGODB_URI: mongodb://shared-mongodb:27017/app2_db
Recommandations et bonnes pratiques
Nommage des services
Adoptez une convention de nommage cohérente pour éviter les conflits DNS :
# Ăvitez les noms gĂ©nĂ©riques
api â
db â
# Préférez des noms descriptifs
project-api â
project-database â
project-worker â
Variables d'environnement
Build time vs Runtime
Distinguez clairement les variables nécessaires au build (préfixées VITE_, REACT_APP_, etc.) et celles utilisées au runtime.
Pour les frameworks frontend, considérez l'injection de configuration au runtime via un fichier env.js généré par l'entrypoint Docker pour éviter de rebuilder à chaque changement d'environnement.
Sécurité
N'exposez jamais les services internes
Les bases de donnĂ©es, Redis, et autres services d'infrastructure ne doivent jamais ĂȘtre exposĂ©s publiquement. Utilisez uniquement le rĂ©seau Docker interne.
Utilisez des secrets forts
Dokploy stocke les variables d'environnement en clair dans sa base de données. Utilisez des mots de passe complexes et unique pour chaque service.
Limitez l'accĂšs Ă l'UI
L'interface Dokploy donne un contrĂŽle total sur l'infrastructure. Restreignez son accĂšs via VPN ou IP whitelisting.
Monitoring et observabilité
Activez les logs d'accĂšs Traefik
Ils sont précieux pour le debugging et la compréhension du trafic :
accessLog:
filePath: "/var/log/traefik/access.log"
format: json
Centralisez les logs applicatifs
Dokploy expose les logs via son UI, mais pour une observabilité avancée, considérez une stack Loki + Grafana.
Limitations et considérations
Dokploy n'est pas adapté à tous les cas
Ăvitez Dokploy pour :
- Infrastructures multi-serveurs complexes (préférez Kubernetes)
- Besoins d'orchestration avancée (auto-scaling horizontal, placement constraints complexes)
- Ăquipes nĂ©cessitant GitOps strict avec approval workflows (prĂ©fĂ©rez ArgoCD)
Dokploy excelle pour :
- Projets personnels et side-projects
- Petites équipes (<10 personnes)
- Applications monolithiques ou microservices simples
- Budgets limités (alternative aux PaaS payants)
Vendor lock-in relatif
Bien que Dokploy soit open-source, migrer vers une autre solution nécessite de reconfigurer manuellement chaque service. Conservez une documentation de votre architecture.
Maturité du projet
Dokploy est un projet relativement jeune. Attendez-vous à des bugs occasionnels et à des fonctionnalités manquantes. La communauté est active, mais le support n'est pas au niveau d'un produit commercial.
Conclusion
La migration vers Dokploy représente un investissement initial de quelques heures, largement compensé par les gains de productivité quotidiens. Pour un développeur gérant une infrastructure personnelle ou de petites équipes souhaitant s'affranchir des coûts récurrents des PaaS, Dokploy offre un excellent compromis entre simplicité d'utilisation et contrÎle de l'infrastructure.
L'automatisation du déploiement continu, couplée à une gestion SSL transparente et une interface moderne, transforme radicalement l'expérience de gestion d'infrastructure. Le simple fait de pouvoir déployer via un git push sans se soucier des détails techniques sous-jacents libÚre un temps considérable pour se concentrer sur le développement de fonctionnalités.
Au-delà de l'outillage, cette migration a été l'occasion d'approfondir ma compréhension des mécanismes fondamentaux du web moderne : protocole ACME, architecture edge computing avec les Workers, patterns de communication dans Docker Swarm. Cette compréhension en profondeur permet de faire des choix architecturaux éclairés et de débugger efficacement lorsque des problÚmes surviennent.
Pour ceux qui hésitent encore : si vous gérez manuellement Docker + Traefik et que vous déployez réguliÚrement, Dokploy vous fera gagner un temps précieux. L'investissement initial est minime, et le retour sur investissement se mesure dÚs les premiÚres semaines.
Stack finale : Dokploy + Docker Swarm + Traefik + Let's Encrypt + Cloudflare Workers
Temps de migration : 8 heures
ROI estimé : ~91 heures économisées par an
Recommandation : âââââ