Docker für die ERP-Bereitstellung in der Produktion: Ein vollständiger Betriebsleitfaden
Organisationen, die ERP-Systeme in Docker-Containern betreiben, berichten von 73 % schnelleren Bereitstellungszyklen und 45 % weniger umgebungsbedingten Vorfällen im Vergleich zu herkömmlichen Bare-Metal-Bereitstellungen. Docker verwandelt die ERP-Bereitstellung von einem mehrtägigen, fehleranfälligen Prozess in einen wiederholbaren, versionierten Vorgang, den jedes Teammitglied ausführen kann.
Dieser Leitfaden deckt den gesamten Lebenszyklus der Ausführung von Unternehmens-ERP-Systemen ab – einschließlich Odoo, benutzerdefinierten NestJS-Backends und Next.js-Frontends – in Docker-Produktionsumgebungen.
Wichtige Erkenntnisse
– Mehrstufige Docker-Builds reduzieren die Größe der ERP-Container-Images um 60–80 % und verbessern so die Bereitstellungsgeschwindigkeit – Docker Compose orchestriert ERP-, Datenbank-, Reverse-Proxy- und Cache-Dienste als eine einzige bereitstellbare Einheit – Benannte Volumes und Bind-Mounts stellen die Datenpersistenz bei Container-Neustarts und -Upgrades sicher
- Gesundheitsprüfungen und Neustartrichtlinien sorgen für eine automatische Wiederherstellung nach vorübergehenden Ausfällen
Architektur eines Docker-ERP-Stacks
Eine ERP-Produktionsbereitstellung umfasst typischerweise fünf oder mehr miteinander verbundene Dienste. Docker Compose definiert diese Dienste deklarativ und gewährleistet so eine konsistente Bereitstellung in allen Umgebungen.
Diensttopologie
Der standardmäßige Dockerized ERP-Stack:
- Anwendungsserver: Die ERP-Laufzeit (Odoo, NestJS oder ähnlich)
- Datenbank: PostgreSQL mit persistentem Volume-Speicher
- Reverse-Proxy: Nginx kümmert sich um die SSL-Terminierung, statische Dateien und das Anforderungsrouting
- Cache-Ebene: Redis für Sitzungsspeicher, Jobwarteschlangen und Anwendungs-Caching
- Hintergrundarbeiter: Asynchrone Jobprozessoren für E-Mails, Berichte und Integrationen
Zu den optionalen Diensten gehören Backup-Container (pg_dump auf cron), Überwachungs-Sidecars (Prometheus-Exporter) und Protokollversender (Fluent Bit).
Mehrstufige Builds für ERP-Anwendungen
Mehrstufige Builds sind für die Produktion von Docker-Images unerlässlich. Sie trennen Abhängigkeiten zur Build-Zeit von der Laufzeit und erzeugen so schlanke, sichere Images.
NestJS-Backend-Build
# 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"]
Next.js Frontend Build
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"]
Bildgrößenvergleich
| Build-Typ | Image Size | Bauzeit |
|---|---|---|
| Einstufig (vollständiges Knotenbild) | 1,8 GB | 4 Minuten |
| Einstufig (Alpin) | 650 MB | 3,5 Minuten |
| Mehrstufig (Alpin) | 180 MB | 5 Minuten |
| Mehrstufige + beschnittene Deps | 120 MB | 5,5 Minuten |
Die Buildzeit von 5,5 Minuten ist akzeptabel, da sie in CI und nicht auf Entwicklermaschinen erfolgt.
Docker Compose für die Produktion
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:
Netzwerkisolation
Die obige Konfiguration verwendet zwei Netzwerke:
- Frontend: Nginx, Web und API (Nginx-Proxys für beide)
- Backend: API, Datenbank und Redis
Auf die Datenbank und Redis kann nicht über den Nginx-Container oder das externe Netzwerk zugegriffen werden. Diese Netzwerksegmentierung ist eine wichtige Sicherheitsmaßnahme.
Volume-Management und Datenpersistenz
Volumes sind der kritischste Teil einer Docker-ERP-Bereitstellung. Wenn Sie Ihre Datenträger verlieren, verlieren Sie Ihre Daten.
Volume-Typen
| Geben Sie | ein Anwendungsfall | Beharrlichkeit | Leistung |
|---|---|---|---|
| Benannte Bände | Datenbank, Redis | Überlebt Containerentfernung | Geschwindigkeit des nativen Dateisystems |
| Halterungen binden | Konfigurationsdateien, Protokolle | An Host-Dateisystem gebunden | Geschwindigkeit des nativen Dateisystems |
| tmpfs mountet | Temporäre Dateien, Geheimnisse | Nur Speicher, geht beim Neustart verloren | Speichergeschwindigkeit |
Backup-Strategie für Docker-Volumes
#!/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
Integritätsprüfungen und Neustartrichtlinien
Produktionscontainer müssen ihren Zustand selbst melden und sich nach Ausfällen automatisch erholen.
Endpunkt zur Anwendungsintegritätsprüfung
// 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;
}
}
}
Richtlinienauswahl neu starten
| Politik | Verhalten | Anwendungsfall |
|---|---|---|
no | Nie neu starten | Entwicklung, einmalige Aufgaben |
on-failure | Nur bei Exit ungleich Null neu starten | Arbeiter, Batch-Jobs |
always | Immer neu starten (auch beim Neustart des Docker-Daemons) | Produktionsdienstleistungen |
unless-stopped | Wie always, berücksichtigt aber manuelle Stopps | Die meisten Produktionsdienstleistungen |
Verwenden Sie unless-stopped für Produktionsdienste. Dies stellt sicher, dass Container nach einem Server-Neustart oder einem Docker-Daemon-Neustart neu gestartet werden, berücksichtigt aber manuelle docker compose stop-Befehle während der Wartung.
Bereitstellungsworkflow
Rolling Updates mit 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
Sicherheit der Datenbankmigration
Führen Sie Migrationen niemals innerhalb des Anwendungsstarts durch. Führen Sie sie stattdessen als separaten Schritt aus:
# Run migrations before deploying new containers
docker compose run --rm api npx drizzle-kit push
# Then deploy the new version
docker compose up -d
Dieses Muster stellt sicher, dass die alte Version unbeeinträchtigt weiterläuft, wenn eine Migration fehlschlägt.
Protokollierung und Debugging
Zentralisierte Protokollierung
# Add to docker-compose.yml
services:
api:
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
labels: "service"
labels:
service: "ecosire-api"
Allgemeine Debugging-Befehle
# 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
Häufig gestellte Fragen
Wie gehen wir mit Datenbankmigrationen in Docker um?
Führen Sie Migrationen als separaten Schritt aus, bevor Sie neue Anwendungscontainer bereitstellen. Verwenden Sie docker compose run --rm api npx drizzle-kit push (oder den Migrationsbefehl Ihres ORM) als Schritt vor der Bereitstellung. Betten Sie die Migrationsausführung niemals in den Container-Startbefehl ein – eine fehlgeschlagene Migration sollte nicht verhindern, dass die aktuelle Version weiterhin ausgeführt wird.
Wie hoch ist der Leistungsaufwand von Docker?
Unter Linux ist der Leistungsaufwand von Docker vernachlässigbar – typischerweise weniger als 2 % für CPU-gebundene Arbeitslasten und kein messbarer Unterschied für E/A-gebundene Arbeitslasten. Unter macOS und Windows läuft Docker in einer virtuellen Maschine, was einen Mehraufwand von 5–15 % verursacht. Für die Produktion (die Linux sein sollte) stellt Docker kein nennenswertes Leistungsproblem dar.
Wie verwalten wir Geheimnisse in Docker?
Fügen Sie niemals Geheimnisse in Dockerfiles- oder docker-compose.yml-Dateien ein. Verwenden Sie Umgebungsvariablendateien (.env), die von der Versionskontrolle ausgeschlossen sind, Docker-Geheimnisse (für den Swarm-Modus) oder externe Geheimnismanager (AWS Secrets Manager, HashiCorp Vault). Für Docker Compose ist eine .env-Datei im Projektstamm der einfachste Ansatz.
Sollten wir Docker Swarm oder Kubernetes verwenden?
Für die meisten KMU-ERP-Bereitstellungen ist Docker Compose ausreichend. Docker Swarm fügt Multi-Host-Orchestrierung mit minimalem Komplexitätsaufwand hinzu. Kubernetes eignet sich, wenn Sie automatische Skalierung, komplexe Netzwerkrichtlinien oder Service-Mesh-Funktionen benötigen. Weitere Informationen zu Entscheidungsframeworks finden Sie in unserem Kubernetes-Skalierungsleitfaden und unserem Microservices-Architekturleitfaden.
Wie gehen wir mit benutzerdefinierten Odoo-Modulen in Docker um?
Hängen Sie benutzerdefinierte Module als Bind-Mount-Volume ein, das auf Ihr Add-On-Verzeichnis verweist. Stellen Sie in der Docker-Datei sicher, dass der Add-On-Pfad in odoo.conf konfiguriert ist. Erstellen Sie für CI/CD ein benutzerdefiniertes Docker-Image, das Ihre Module einbettet und so die Versionskonsistenz gewährleistet. Informationen zur Odoo-spezifischen Konfiguration finden Sie in unserem bestehenden Docker Odoo-Bereitstellungsleitfaden.
Was als nächstes kommt
Docker ist die Grundlage für die moderne ERP-Bereitstellung. Sobald Ihr Container-Stack stabil ist, erkunden Sie Bereitstellungsstrategien ohne Ausfallzeiten, Produktionsüberwachung und Infrastruktur als Code, um eine vollständig automatisierte Betriebspipeline aufzubauen.
Kontaktieren Sie ECOSIRE für Beratung zur Docker-Bereitstellung oder erkunden Sie unsere Odoo-Implementierungsdienste für die vollständig verwaltete Container-ERP-Bereitstellung.
Herausgegeben von ECOSIRE – hilft Unternehmen dabei, Unternehmenssoftware sicher bereitzustellen.
Geschrieben von
ECOSIRE Research and Development Team
Entwicklung von Enterprise-Digitalprodukten bei ECOSIRE. Einblicke in Odoo-Integrationen, E-Commerce-Automatisierung und KI-gestützte Geschäftslösungen.
Verwandte Artikel
Power BI-Implementierung: Best Practices für Unternehmen für 2026
Enterprise Power BI-Implementierungsleitfaden zu Arbeitsbereichsarchitektur, Gateway-Einrichtung, Lizenzplanung, Bereitstellungspipelines, Governance und Einführung.
Automatisierung der Kreditorenbuchhaltung: Reduzieren Sie die Bearbeitungskosten um 80 Prozent
Implementieren Sie die Automatisierung der Kreditorenbuchhaltung, um die Kosten für die Rechnungsverarbeitung mit OCR, Drei-Wege-Abgleich und ERP-Workflows von 15 auf 3 US-Dollar pro Rechnung zu senken.
KI in der Buchhaltungs- und Buchhaltungsautomatisierung: Der CFO-Implementierungsleitfaden
Automatisieren Sie die Buchhaltung mit KI für Rechnungsverarbeitung, Bankabstimmung, Spesenmanagement und Finanzberichterstattung. 85 % schnellere Schließzyklen.