Docker-Container — Entwicklung und Bereitstellung vereinfachen
Docker in der Praxis: Von Legacy zu modernen Microservices
Nach vielen Jahren in der Softwareentwicklung habe ich gelernt: Die interessantesten Projekte sind nicht die, wo alles perfekt und modern ist. Es sind die, wo man mit der Realität umgehen muss – mit gewachsenen Systemen, Legacy-Code und der Herausforderung, Altes und Neues miteinander zu verbinden.
Genau in so einer Welt arbeite ich seit Jahren. Und genau hier zeigt Docker seine wahre Stärke.
Der Ausgangspunkt: Eine gewachsene Infrastruktur
Vor einigen Jahren sah unsere Entwicklungslandschaft noch klassisch aus:
- Jenkins als Build- und Deployment-Tool
- Manuelle Setups für Entwicklungsumgebungen
- Oracle-Datenbanken, die auf jedem Entwicklerrechner anders konfiguriert waren
- Deployments, die funktionierten – aber oft nur nach mehreren Versuchen
Das erste Docker-Experiment: Oracle DB
Unser erster Berührungspunkt mit Docker war pragmatisch: Oracle-Datenbank für die Entwicklung.
Vorher bedeutete Oracle-Setup:
- 2-3 Stunden Installation und Konfiguration
- Unterschiedliche Versionen auf verschiedenen Rechnern
- "Bei mir läuft's" – beim Kollegen nicht
docker run oracle-db
10 Minuten. Gleiche Version überall. Reproduzierbar.
Das war der Moment, wo ich verstanden habe: Docker löst nicht primär technische Probleme. Es löst menschliche Probleme.
Neue Entwickler waren produktiv, statt frustriert. Seniors verloren keine Zeit mehr mit Setup-Support. Das allein rechtfertigte den Aufwand.
Der Wendepunkt: Azure CI/CD und eine komplexe E-Commerce-Architektur
Dann kam der große Schritt: Migration zu Azure DevOps mit einer vollständig containerbasierten CI/CD-Pipeline – und gleichzeitig die Integration einer etablierten E-Commerce-Plattform durch einen Entwicklungspartner.
Die Herausforderung: Hybrid-Architektur
Große E-Commerce-Plattformen sind über Jahre gewachsen. Das bedeutet auch: Legacy ist Realität.
Unsere Architektur heute:
- Eine etablierte Commerce-Plattform – bewährt, aber mit älteren Technologien
- PWA Storefront – moderne Angular-basierte Progressive Web App
- Moderne Microservices – Angebots-Service, Händler-Service, Produkt-Service
- SPA-basiertes Admin-Portal – komplett modern entwickelt
Das ist Enterprise-Realität: Nicht alles kann über Nacht neu geschrieben werden. Man muss mit dem arbeiten, was da ist.
Was Docker hier konkret löst
1. Service-Isolation trotz heterogener Technologien
Wir haben Services auf unterschiedlichen Tech-Stacks:
- Legacy-Plattform (Java-basiert, ältere Frameworks)
- Moderne Backend-Services (aktuelle Java-Versionen, moderne Architekturen)
- Frontend (Angular PWA, Node.js-basiert)
Ergebnis: Ein Entwickler kann am Frontend arbeiten, ohne Java installiert zu haben. Ein Backend-Entwickler kann verschiedene Service-Versionen parallel testen.
2. CI/CD-Pipeline wird konsistent und schnell
Der Wechsel von Jenkins zu Azure DevOps mit Docker brachte messbare Verbesserungen.
Vorher (Jenkins):
- Build-Zeit: 15-25 Minuten (je nach Service)
- Deployment: manuell, fehleranfällig
- Unterschiede zwischen Build-Umgebung und Production
- Build-Zeit: 8-12 Minuten für die meisten Services
- Deployment: automatisiert via Helm Charts
- Identische Container von Dev bis Production
3. Helm Charts: Deployment wird deklarativ
Helm Charts haben das Deployment revolutioniert. Statt manueller Konfiguration beschreibt eine YAML-Datei das gesamte Deployment:
yamlservice: offer-service
version: 1.2.3
replicas: 3
resources: ...
Ein Deployment über mehrere Umgebungen (Dev, Staging, Production) wird dadurch:
- Nachvollziehbar (alles ist in Git versioniert)
- Wiederholbar (gleicher Befehl, gleiches Ergebnis)
- Sicher (Rollback mit einem Befehl möglich)
4. Die Legacy-Bridge: Alt und Neu koexistieren
Hier zeigt sich die wahre Stärke von Docker: Es ermöglicht Koexistenz.
Die Legacy-Plattform läuft in ihren Containern mit ihren spezifischen Anforderungen. Die modernen Services laufen in ihren Containern mit modernen Stacks. Die PWA kommuniziert mit beiden – transparent durch Docker-Networking.
Wir müssen die alte Plattform nicht neu schreiben. Wir können sie schrittweise durch moderne Services ersetzen – Service für Service. Docker macht diesen evolutionären Ansatz praktikabel.
Was man dabei lernen muss (die kritischen Punkte)
Nach Jahren mit Docker in dieser komplexen Umgebung habe ich auch gelernt: Es ist kein Allheilmittel.
1. Performance-Unterschiede sind real
Die modernen Services bauen schnell und laufen performant. Aber manche ältere Services oder Komponenten sind langsamer.
Warum?
- Große Images (manchmal 1-2 GB)
- Komplexe Build-Prozesse
- Viele Dependencies
2. Debugging wird komplexer
Wenn ein Service im Container nicht funktioniert, ist Debugging schwieriger:
- Logs sind über mehrere Container verteilt
- Netzwerk-Probleme zwischen Containern sind subtil
- Der Zugriff auf laufende Container erfordert zusätzliche Schritte
3. Image-Management braucht Disziplin
Mit Azure Container Registry und vielen Services haben wir hunderte Images. Ohne klare Versionierung und Cleanup-Strategie wird es schnell unübersichtlich.
Learnings:
- Semantic Versioning konsequent nutzen
- Alte Images regelmäßig löschen
- Security-Scans automatisieren
4. Nicht alles gehört in Container
Ich habe auch gelernt: Manche Komponenten laufen besser außerhalb von Containern. Besonders bei I/O-intensiven Operationen oder wenn externe Tools integriert werden müssen.
Die Frage ist nicht: "Kann ich das dockern?" Die Frage ist: "Sollte ich das dockern?"
Was ich wirklich gelernt habe
Nach Jahren in dieser Hybrid-Welt zwischen Legacy und modernen Microservices ist meine wichtigste Erkenntnis:
Docker ist ein Enabler für schrittweise Transformation.
Es erlaubt uns:
- Alte Systeme am Leben zu halten, während wir neue bauen
- Verschiedene Technologien parallel zu betreiben
- Services unabhängig voneinander zu entwickeln und zu deployen
- Teams autonom arbeiten zu lassen
- Gute Architektur-Entscheidungen
- Klare Dokumentation
- Verständnis der eigenen Systeme
- Disziplinierte Entwicklungsprozesse
Wann macht Docker Sinn?
Nach dieser Erfahrung würde ich Docker empfehlen für:
- ✓ Microservices-Architekturen – Jeder Service in seinem Container, klare Grenzen, unabhängige Deployments.
- ✓ Hybrid-Umgebungen (Legacy + Modern) – Ermöglicht schrittweise Migration ohne Big-Bang-Rewrite.
- ✓ Teams mit mehreren Entwicklern – Einheitliche Entwicklungsumgebungen sparen enorm viel Zeit.
- ✓ CI/CD-Pipelines – Build once, run anywhere – vom lokalen Test bis Production.
- ✓ Cloud-Deployments – Fast alle Cloud-Plattformen unterstützen Container nativ.
- ✗ Sehr einfachen Projekten – Eine statische Website braucht keinen Container-Overhead.
- ✗ Teams ohne Docker-Erfahrung unter Zeitdruck – Die Lernkurve ist real. Lieber Zeit nehmen oder erstmal klassisch arbeiten.
- ✗ Legacy-Monolithen ohne klare Modularisierung – Einen Monolithen in einen Container zu packen löst keine Architektur-Probleme.
- ✗ Performance-kritische Anwendungen mit hohem I/O – Der Container-Overhead kann hier spürbar sein.
Der Blick nach vorne
Diese Jahre mit Docker in einer komplexen Enterprise-Umgebung haben meine Perspektive auf Softwareentwicklung geprägt.
Ich habe gelernt:
Technologie muss Probleme lösen, nicht schaffen. Docker löst echte Probleme – wenn man es richtig einsetzt.
Pragmatismus schlägt Purismus. Die perfekte Architektur auf dem Papier nützt nichts. Die Hybrid-Lösung, die funktioniert, ist besser.
Evolution schlägt Revolution. Komplette Neuentwicklungen sind oft nicht möglich. Aber schrittweiser Ersatz funktioniert.
Teams sind wichtiger als Tools. Docker ist nur so gut wie das Team, das es einsetzt. Ohne gemeinsames Verständnis, klare Standards und Disziplin wird auch Docker zum Problem.
Was das für mich bedeutet
Diese Erfahrung – zwischen Legacy und modernen Microservices, zwischen alten und neuen Technologien – hat mir gezeigt, worum es in der Softwareentwicklung wirklich geht:
Nicht die coolste Technologie zu verwenden, sondern die richtige.
Nicht alles neu zu bauen, sondern smart mit dem zu arbeiten, was da ist.
Nicht Perfektion anzustreben, sondern kontinuierliche Verbesserung.
Das ist die Denkweise, die ich in zukünftige Projekte mitbringe.
Denn am Ende geht es nicht um Container, Microservices oder CI/CD-Pipelines.
Es geht darum, Software zu bauen, die echte Probleme löst – pragmatisch, nachhaltig und mit Mehrwert für die Menschen, die damit arbeiten.