Docker pour le déploiement de l'ERP de production : un guide complet des opérations
Les organisations exécutant des systèmes ERP dans des conteneurs Docker signalent des cycles de déploiement 73 % plus rapides et 45 % d'incidents liés à l'environnement en moins par rapport aux déploiements nus traditionnels. Docker transforme le déploiement ERP d'un processus sur plusieurs jours et sujet aux erreurs en une opération reproductible et contrôlée par les versions que n'importe quel membre de l'équipe peut exécuter.
Ce guide couvre le cycle de vie complet de l'exécution des systèmes ERP d'entreprise --- y compris Odoo, les backends NestJS personnalisés et les frontends Next.js --- dans les environnements Docker de production.
Points clés à retenir
- Les versions Docker en plusieurs étapes réduisent la taille des images des conteneurs ERP de 60 à 80 %, améliorant ainsi la vitesse de déploiement.
- Docker Compose orchestre les services ERP, base de données, proxy inverse et cache comme une seule unité déployable
- Les volumes nommés et les montages de liaison garantissent la persistance des données lors des redémarrages et des mises à niveau des conteneurs.
- Les contrôles de santé et les politiques de redémarrage permettent une récupération automatique en cas de pannes transitoires.
Architecture d'une pile ERP Dockerisée
Un déploiement ERP de production implique généralement cinq services interconnectés ou plus. Docker Compose définit ces services de manière déclarative, garantissant un déploiement cohérent dans tous les environnements.
Topologie des services
La pile ERP Dockerisée standard :
- Serveur d'applications : Le runtime ERP (Odoo, NestJS ou similaire)
- Base de données : PostgreSQL avec stockage de volume persistant
- Proxy inverse : Nginx gère la terminaison SSL, les fichiers statiques et le routage des requêtes
- Couche de cache : Redis pour le stockage de sessions, les files d'attente de tâches et la mise en cache des applications
- Travailleurs d'arrière-plan : processeurs de tâches asynchrones pour les e-mails, les rapports et les intégrations
Les services optionnels incluent des conteneurs de sauvegarde (pg_dump sur cron), des side-cars de surveillance (exportateurs Prometheus) et des expéditeurs de journaux (Fluent Bit).
Constructions en plusieurs étapes pour les applications ERP
Les builds en plusieurs étapes sont essentielles pour la production d’images Docker. Ils séparent les dépendances au moment de la construction du temps d'exécution, produisant des images simples et sécurisées.
Construction du backend NestJS
# Stage 1: Install dependencies and build
FROM node:20-alpine AS builder
WORKDIR /app
# Install pnpm
RUN corepack enable
# Copy workspace configuration
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./
COPY packages/ ./packages/
COPY apps/api/package.json ./apps/api/
# Install dependencies
RUN pnpm install --frozen-lockfile
# Copy source and build
COPY apps/api/ ./apps/api/
RUN pnpm --filter @ecosire/db build
RUN pnpm --filter @ecosire/types build
RUN pnpm --filter @ecosire/validators build
RUN pnpm --filter @ecosire/api build
# Stage 2: Production runtime
FROM node:20-alpine AS runner
WORKDIR /app
RUN addgroup -g 1001 -S appgroup && \
adduser -S appuser -u 1001 -G appgroup
COPY --from=builder --chown=appuser:appgroup /app/apps/api/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=builder --chown=appuser:appgroup /app/apps/api/package.json ./
USER appuser
EXPOSE 3001
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3001/health || exit 1
CMD ["node", "dist/main.js"]
Construction frontale Next.js
FROM node:20-alpine AS builder
WORKDIR /app
RUN corepack enable
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./
COPY packages/ ./packages/
COPY apps/web/package.json ./apps/web/
RUN pnpm install --frozen-lockfile
COPY apps/web/ ./apps/web/
RUN pnpm --filter @ecosire/web build
FROM node:20-alpine AS runner
WORKDIR /app
RUN addgroup -g 1001 -S appgroup && \
adduser -S appuser -u 1001 -G appgroup
COPY --from=builder --chown=appuser:appgroup /app/apps/web/.next/standalone ./
COPY --from=builder --chown=appuser:appgroup /app/apps/web/.next/static ./.next/static
COPY --from=builder --chown=appuser:appgroup /app/apps/web/public ./public
USER appuser
EXPOSE 3000
ENV NODE_ENV=production
CMD ["node", "server.js"]
Comparaison de la taille de l'image
| Type de construction | Taille de l'image | Temps de construction |
|---|---|---|
| En une seule étape (image complète du nœud) | 1,8 Go | 4 minutes |
| Mono-étage (alpin) | 650 Mo | 3,5 minutes |
| Multi-étapes (alpin) | 180 Mo | 5 minutes |
| Dépôts multi-étages + taillés | 120 Mo | 5,5 minutes |
Le temps de construction de 5,5 minutes est acceptable car cela se produit dans CI, pas sur les machines des développeurs.
Docker Compose pour la production
version: "3.8"
services:
api:
build:
context: .
dockerfile: apps/api/Dockerfile
environment:
- DATABASE_URL=postgresql://app:${DB_PASSWORD}@db:5432/ecosire
- REDIS_URL=redis://redis:6379
- NODE_ENV=production
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
restart: unless-stopped
networks:
- backend
- frontend
web:
build:
context: .
dockerfile: apps/web/Dockerfile
environment:
- API_URL=http://api:3001
- NODE_ENV=production
depends_on:
- api
restart: unless-stopped
networks:
- frontend
db:
image: postgres:17-alpine
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ecosire
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d ecosire"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- backend
redis:
image: redis:7-alpine
command: redis-server --requirepass ${REDIS_PASSWORD} --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- backend
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./infrastructure/nginx/production.conf:/etc/nginx/conf.d/default.conf:ro
- ./certbot/conf:/etc/letsencrypt:ro
- ./certbot/www:/var/www/certbot:ro
depends_on:
- web
- api
restart: unless-stopped
networks:
- frontend
volumes:
postgres-data:
redis-data:
networks:
frontend:
backend:
Isolement du réseau
La configuration ci-dessus utilise deux réseaux :
- frontend : Nginx, Web et API (proxys Nginx pour les deux)
- backend : API, base de données et Redis
La base de données et Redis ne sont pas accessibles depuis le conteneur Nginx ou le réseau externe. Cette segmentation du réseau est une pratique de sécurité critique.
Gestion des volumes et persistance des données
Les volumes constituent la partie la plus critique d’un déploiement ERP Dockerisé. Perdez vos volumes et vous perdez vos données.
###Types de volumes
| Tapez | Cas d'utilisation | Persistance | Performances |
|---|---|---|---|
| Volumes nommés | Base de données, Redis | Survit au retrait du conteneur | Vitesse du système de fichiers natif |
| Lier les montures | Fichiers de configuration, journaux | Lié au système de fichiers hôte | Vitesse du système de fichiers natif |
| montages tmpfs | Fichiers temporaires, secrets | Mémoire uniquement, perdue au redémarrage | Vitesse de la mémoire |
Stratégie de sauvegarde pour les volumes Docker
#!/bin/bash
# backup-volumes.sh - Run via cron every 6 hours
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/opt/backups"
# Stop the application briefly for consistent backup
docker compose stop api web
# Backup PostgreSQL
docker compose exec -T db pg_dump -U app ecosire | gzip > "$BACKUP_DIR/db_$TIMESTAMP.sql.gz"
# Backup Redis
docker compose exec -T redis redis-cli -a "$REDIS_PASSWORD" BGSAVE
sleep 5
docker cp $(docker compose ps -q redis):/data/dump.rdb "$BACKUP_DIR/redis_$TIMESTAMP.rdb"
# Restart services
docker compose start api web
# Upload to S3
aws s3 sync "$BACKUP_DIR" "s3://company-backups/docker-volumes/" --exclude "*.tmp"
# Retain 30 days locally
find "$BACKUP_DIR" -name "*.gz" -mtime +30 -delete
find "$BACKUP_DIR" -name "*.rdb" -mtime +30 -delete
## Vérifications de santé et politiques de redémarrage
Les conteneurs de production doivent signaler eux-mêmes leur état de santé et se remettre automatiquement des pannes.
Point de terminaison de vérification de l'état de l'application
// health.controller.ts
@Controller('health')
export class HealthController {
constructor(
private readonly db: DatabaseService,
private readonly redis: RedisService,
) {}
@Get()
@Public()
async check() {
const checks = {
database: await this.checkDatabase(),
redis: await this.checkRedis(),
uptime: process.uptime(),
memory: process.memoryUsage(),
};
const healthy = checks.database && checks.redis;
return { status: healthy ? 'ok' : 'degraded', checks };
}
private async checkDatabase(): Promise<boolean> {
try {
await this.db.execute('SELECT 1');
return true;
} catch {
return false;
}
}
private async checkRedis(): Promise<boolean> {
try {
await this.redis.ping();
return true;
} catch {
return false;
}
}
}
Redémarrer la sélection de la stratégie
| Politique | Comportement | Cas d'utilisation |
|---|---|---|
no | Ne redémarrez jamais | Développement, tâches ponctuelles |
on-failure | Redémarrer uniquement en cas de sortie non nulle | Travailleurs, travaux par lots |
always | Toujours redémarrer (y compris lors du redémarrage du démon Docker) | Prestations de production |
unless-stopped | Comme always mais respecte les arrêts manuels | La plupart des services de production |
Utilisez unless-stopped pour les services de production. Cela garantit le redémarrage des conteneurs après le redémarrage du serveur ou le redémarrage du démon Docker, mais respecte les commandes manuelles docker compose stop pendant la maintenance.
Flux de travail de déploiement
Mises à jour progressives avec Docker Compose
#!/bin/bash
# deploy.sh - Zero-downtime deployment
set -e
echo "Pulling latest code..."
git pull origin main
echo "Building new images..."
docker compose build --no-cache api web
echo "Rolling update - API first..."
docker compose up -d --no-deps api
sleep 10
# Verify API health
if ! curl -sf http://localhost:3001/health > /dev/null; then
echo "API health check failed, rolling back..."
docker compose up -d --no-deps api
exit 1
fi
echo "Rolling update - Web..."
docker compose up -d --no-deps web
sleep 5
# Verify Web health
if ! curl -sf http://localhost:3000 > /dev/null; then
echo "Web health check failed, rolling back..."
docker compose up -d --no-deps web
exit 1
fi
echo "Deployment complete!"
docker compose ps
Sécurité de la migration des bases de données
N’exécutez jamais de migrations au démarrage de l’application. Au lieu de cela, exécutez-les dans le cadre d'une étape distincte :
# Run migrations before deploying new containers
docker compose run --rm api npx drizzle-kit push
# Then deploy the new version
docker compose up -d
Ce modèle garantit qu'en cas d'échec d'une migration, l'ancienne version continue de s'exécuter sans être affectée.
Journalisation et débogage
Journalisation centralisée
# Add to docker-compose.yml
services:
api:
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
labels: "service"
labels:
service: "ecosire-api"
Commandes de débogage courantes
# View logs for a specific service
docker compose logs -f api --tail 100
# Execute a shell inside a running container
docker compose exec api sh
# View resource usage
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}"
# Inspect container networking
docker compose exec api ping db
# View container environment variables
docker compose exec api env | sort
Questions fréquemment posées
Comment gérer les migrations de bases de données dans Docker ?
Exécutez les migrations dans le cadre d’une étape distincte avant de déployer de nouveaux conteneurs d’applications. Utilisez docker compose run --rm api npx drizzle-kit push (ou la commande de migration de votre ORM) comme étape de pré-déploiement. N'intégrez jamais l'exécution de la migration dans la commande de démarrage du conteneur : un échec de migration ne devrait pas empêcher la version actuelle de continuer à s'exécuter.
Quelle est la surcharge de performances de Docker ?
Sous Linux, la surcharge de performances de Docker est négligeable : généralement inférieure à 2 % pour les charges de travail liées au processeur et aucune différence mesurable pour les charges de travail liées aux E/S. Sous macOS et Windows, Docker s'exécute dans une machine virtuelle, ce qui ajoute 5 à 15 % de surcharge. Pour la production (qui devrait être Linux), Docker ne constitue pas un problème de performances significatif.
Comment gérer les secrets dans Docker ?
Ne mettez jamais de secrets dans les fichiers Dockerfiles ou docker-compose.yml. Utilisez des fichiers de variables d'environnement (.env) exclus du contrôle de version, des secrets Docker (pour le mode Swarm) ou des gestionnaires de secrets externes (AWS Secrets Manager, HashiCorp Vault). Pour Docker Compose, un fichier .env à la racine du projet est l'approche la plus simple.
Devrions-nous utiliser Docker Swarm ou Kubernetes ?
Pour la plupart des déploiements ERP PME, Docker Compose est suffisant. Docker Swarm ajoute une orchestration multi-hôtes avec une complexité minimale. Kubernetes est approprié lorsque vous avez besoin d'une mise à l'échelle automatique, de politiques de réseau complexes ou de fonctionnalités de maillage de services. Consultez notre guide de mise à l'échelle Kubernetes et notre guide d'architecture des microservices pour connaître les cadres de décision.
Comment gérer les modules personnalisés Odoo dans Docker ?
Montez les modules personnalisés en tant que volume de montage de liaison pointant vers votre répertoire de modules complémentaires. Dans le Dockerfile, assurez-vous que le chemin des modules complémentaires est configuré dans odoo.conf. Pour CI/CD, créez une image Docker personnalisée qui s'intègre dans vos modules, garantissant ainsi la cohérence des versions. Consultez notre Guide de déploiement Docker Odoo existant pour la configuration spécifique à Odoo.
Ce qui vient ensuite
Docker est la base du déploiement ERP moderne. Une fois que votre pile conteneurisée est stable, explorez les stratégies de déploiement sans temps d'arrêt, surveillance de la production et infrastructure as code pour créer un pipeline d'opérations entièrement automatisé.
Contactez ECOSIRE pour des conseils en matière de déploiement Docker, ou explorez nos services de mise en œuvre Odoo pour un déploiement ERP conteneurisé entièrement géré.
Publié par ECOSIRE – aider les entreprises à déployer des logiciels d'entreprise en toute confiance.
Rédigé par
ECOSIRE Research and Development Team
Création de produits numériques de niveau entreprise chez ECOSIRE. Partage d'analyses sur les intégrations Odoo, l'automatisation e-commerce et les solutions d'entreprise propulsées par l'IA.
Articles connexes
Automatisation des comptes fournisseurs : réduisez les coûts de traitement de 80 %
Mettez en œuvre l'automatisation des comptes fournisseurs pour réduire les coûts de traitement des factures de 15 $ à 3 $ par facture grâce à l'OCR, à la correspondance à trois voies et aux workflows ERP.
L'IA dans l'automatisation de la comptabilité et de la tenue de livres : le guide de mise en œuvre du CFO
Automatisez la comptabilité avec l'IA pour le traitement des factures, le rapprochement bancaire, la gestion des dépenses et les rapports financiers. Cycles de fermeture 85 % plus rapides.
Modèles de passerelle API et meilleures pratiques pour les applications modernes
Implémentez des modèles de passerelle API, notamment la limitation de débit, l'authentification, le routage des requêtes, les disjoncteurs et la gestion des versions API pour les architectures Web évolutives.