Einleitung

Moderne Webanwendungen laufen selten als ein einziger monolithischer Prozess. Stattdessen bestehen sie aus mehreren zusammenarbeitenden Diensten: einem Frontend, einer API, einer Datenbank, einem Cache, einer Nachrichtenwarteschlange und vielleicht einem Jobläufer. Die manuelle Verwaltung des Lebenszyklus jedes Containers, seiner Vernetzung und seiner Abhängigkeiten wird schnell fehleranfällig und zeitaufwendig. Docker Compose und Nginx zusammen bieten eine kampferprobte, produktionsfreundliche Lösung zum Definieren und Bereitstellen dieser Multicontainer-Systeme mit minimaler Reibung. Docker Compose ermöglicht es Ihnen, Ihren gesamten Anwendungsstack in einer einzigen YAML-Datei zu beschreiben, während Nginx als zuverlässiger Reverse-Proxy und Load-Balancer fungiert, der Datenverkehr an den entsprechenden Dienst weiterleitet. In diesem erweiterten Leitfaden werden wir durch eine realistische Einrichtung gehen, in Konfigurationsdetails graben, Sicherheitsbest Practices abdecken und Ihnen zeigen, wie Sie von der Entwicklung bis zur Produktion skalieren können.

Voraussetzungen

Bevor Sie eintauchen, stellen Sie sicher, dass Sie Folgendes auf Ihrem System installiert haben:

  • Docker Engine (Version 20.10 oder neuer) – Docker installieren
  • Docker Compose (V2 ist jetzt in Docker CLI integriert; überprüfen Sie mit ) – Dockcompose installieren
  • Grundlegende Vertrautheit] mit Terminal-Befehlen und YAML-Syntax.

Optional einen Domainnamen auf Ihren Server haben, wenn Sie planen, den SSL-Konfigurationsabschnitt zu folgen.

Docker Compose in der Tiefe verstehen

Docker Compose ist nicht nur ein einfacher „Docker Run Wrapper. Es ist ein deklaratives Tool, mit dem Sie Dienste, Netzwerke, Volumes, Umgebungsvariablen, Neustartrichtlinien und Gesundheitschecks in einer einzigen Datei mit dem Namen FLT: 1 definieren können. Die Compose-Spezifikation (jetzt Teil der FLT: 0) Compose Specification [FLT: 1] standardisiert, wie Multicontainer-Anwendungen beschrieben werden, wodurch Ihr Setup über verschiedene CI / CD-Pipelines und Cloud-Anbieter hinweg portabel wird.

Dienstleistungen

Jedes Container-Image, seine Ports, Volumes, Umgebung und Abhängigkeiten werden unter dem Schlüssel definiert. Dienste können über ein dediziertes Brückennetzwerk miteinander kommunizieren, das Compose automatisch erstellt. Das bedeutet, dass Sie niemals Host-Ports für die Inter-Service-Kommunikation öffnen müssen - nur der Reverse-Proxy muss Ports der Außenwelt aussetzen.

Netze

Standardmäßig erstellt Compose ein einzelnes Netzwerk für alle Dienste, indem sie ihnen DNS-basierte Service-Erkennung mit dem Servicenamen als Hostnamen gibt. Zum Beispiel kann ein Dienst mit dem Namen von anderen Diensten einfach als erreicht werden. Sie können auch benutzerdefinierte Netzwerke für die Isolation definieren, beispielsweise indem Sie nur den Reverse-Proxy in ein öffentlich zugängliches Netzwerk einfügen und Datenbankcontainer in einem internen Netzwerk halten.

networks:
 frontend:
 backend:
services:
 nginx:
 networks:
 - frontend
 app:
 networks:
 - frontend
 - backend
 db:
 networks:
 - backend

Volumen

Volumes sind der bevorzugte Mechanismus für die Persistenz von Daten, die von Docker-Containern generiert werden. In Compose können Sie benannte Volumes auf der obersten Ebene deklarieren und in Dienste einfügen. Dies ist für Datenbanken, Datei-Uploads und jeden Stateful Service unerlässlich.

volumes:
 db_data:
services:
 postgres:
 image: postgres:16
 volumes:
 - db_data:/var/lib/postgresql/data

Umweltvariablen

Konfiguration mit Umgebungsvariablen externalisieren. Sie können sie in der Compose-Datei für die Entwicklung fest codieren, aber für die Produktion sollten Sie -Dateien oder Docker-Geheimnisse verwenden. Compose lädt automatisch eine -Datei im selben Verzeichnis, wenn Sie nicht angeben.

services:
 api:
 image: my-api:latest
 env_file:
 - ./api.env
 environment:
 - NODE_ENV=production

Konfiguration von Nginx als Reverse Proxy – Advanced

Nginx glänzt als Reverse-Proxy wegen seiner hohen Leistung, geringen Speicher-Fußabdruck und reiche Feature-Set. In einer Multi-Container-Architektur, Nginx sitzt am Rand, akzeptiert Client-Anfragen und leitet sie an den entsprechenden Dienst basierend auf der Anforderung URI, Header oder sogar Body-Inhalte. Es kann auch SSL-Terminierung, Caching, Rate-Limiting und Load-Balancing.

Basic Reverse Proxy mit mehreren Upstreams

Hier ist eine vollständigere Konfiguration, die zeigt, wie der Datenverkehr zwischen zwei verschiedenen Anwendungen aufgeteilt wird, einschließlich der Handhabung von statischen Assets und WebSockets:

upstream app1_upstream {
 server app1:8000;
}

upstream app2_upstream {
 server app2:8001;
}

server {
 listen 80;
 server_name example.com;
 return 301 https://$server_name$request_uri;
}

server {
 listen 443 ssl http2;
 server_name example.com;

 ssl_certificate /etc/nginx/certs/fullchain.pem;
 ssl_certificate_key /etc/nginx/certs/privkey.pem;

 # Security headers
 add_header X-Frame-Options "SAMEORIGIN" always;
 add_header X-Content-Type-Options "nosniff" always;
 add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

 # App 1 – main web frontend
 location / {
 proxy_pass http://app1_upstream;
 proxy_set_header Host $host;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Forwarded-Proto $scheme;
 }

 # App 2 – admin dashboard
 location /admin/ {
 proxy_pass http://app2_upstream/;
 proxy_set_header Host $host;
 proxy_set_header X-Real-IP $remote_addr;
 }

 # WebSocket support (e.g., for live updates)
 location /ws/ {
 proxy_pass http://app1_upstream;
 proxy_http_version 1.1;
 proxy_set_header Upgrade $http_upgrade;
 proxy_set_header Connection "upgrade";
 }

 # Static assets – serve directly for better performance
 location /static/ {
 alias /var/www/static/;
 expires 30d;
 add_header Cache-Control "public, immutable";
 }
}

Beachten Sie die Verwendung von Blöcken. Sie ermöglichen es Ihnen, eine Gruppe von Servern für den Load Balancing zu definieren. Selbst bei einem einzelnen Server macht es die Verwendung einer vorgelagerten Gruppe einfach, später weitere Replikate hinzuzufügen, ohne den Serverblock zu berühren.

SSL/TLS mit Let's Encrypt

Für die Produktion ist die Bereitstellung von HTTPS nicht verhandelbar. Sie können die Zertifikatsverlängerung mit Certbot oder acme.sh innerhalb eines Sidecar-Containers automatisieren. Ein gängiges Muster ist das Einhängen der Zertifikate als Volumes in den Nginx-Container.

services:
 nginx:
 image: nginx:alpine
 volumes:
 - ./nginx.conf:/etc/nginx/conf.d/default.conf
 - ./certs:/etc/nginx/certs:ro
 - ./static:/var/www/static:ro
 ports:
 - "80:80"
 - "443:443"
 depends_on:
 - app1
 - app2

Für die automatische Verlängerung können Sie einen Begleitcontainer wie oder hinzufügen, der einen Cron-Job ausführt und Nginx neu lädt, wenn Zertifikate aktualisiert werden.

Lastausgleich und Gesundheitschecks

Wenn Sie einen Dienst auf mehrere Replikate skalieren, kann Nginx Anfragen mit Round-Robin, Least Connections oder IP-Hash verteilen.

upstream api_servers {
 least_conn;
 server api:80 max_fails=3 fail_timeout=30s;
}

Um ungesunde Container zu erkennen, kann Nginx mit konfiguriert werden (erfordert NGINX Plus oder nutzt die aus der Open-Source-Version mit einem kleinen Workaround).

Erstellen der Docker Compose-Datei - ein Beispiel aus der realen Welt

Lassen Sie uns alles zu einer praktischen Compose-Datei für eine Webanwendung kombinieren, die aus einer Node.js-API, einem React-Frontend von Nginx, einer PostgreSQL-Datenbank und einem Redis-Cache besteht. Der Nginx-Container dient statischen Dateien und Proxy-API-Anforderungen.

version: "3.9"

services:
 nginx:
 image: nginx:alpine
 container_name: reverse-proxy
 restart: unless-stopped
 volumes:
 - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
 - ./frontend/build:/var/www/frontend:ro
 - ./certs:/etc/nginx/certs:ro
 ports:
 - "80:80"
 - "443:443"
 depends_on:
 - api
 - frontend
 networks:
 - public

 frontend:
 image: my-frontend:latest
 # In production, frontend is built into static files and served by Nginx
 # This container may run a dev server, but Nginx will bypass it for static files
 container_name: frontend-dev
 ports:
 - "3000:3000"
 networks:
 - public
 # healthcheck: ...

 api:
 image: my-api:latest
 container_name: api-server
 restart: unless-stopped
 env_file:
 - ./api/.env.production
 depends_on:
 postgres:
 condition: service_healthy
 redis:
 condition: service_started
 networks:
 - public
 - internal
 healthcheck:
 test: ["CMD", "curl", "-f", "http://localhost:4000/health"]
 interval: 30s
 timeout: 10s
 retries: 3

 postgres:
 image: postgres:16-alpine
 container_name: database
 restart: unless-stopped
 environment:
 POSTGRES_USER: app_user
 POSTGRES_DB: app_db
 POSTGRES_PASSWORD_FILE: /run/secrets/db_password
 volumes:
 - pgdata:/var/lib/postgresql/data
 secrets:
 - db_password
 networks:
 - internal
 healthcheck:
 test: ["CMD-SHELL", "pg_isready -U app_user"]
 interval: 10s
 timeout: 5s
 retries: 5

 redis:
 image: redis:7-alpine
 container_name: cache
 restart: unless-stopped
 volumes:
 - redisdata:/data
 networks:
 - internal
 healthcheck:
 test: ["CMD", "redis-cli", "ping"]
 interval: 10s
 timeout: 3s

volumes:
 pgdata:
 redisdata:

networks:
 public:
 internal:
 internal: true

secrets:
 db_password:
 file: ./secrets/db_password.txt

Schlüsselpunkte in dieser Datei:

  • Netzwerkisolation: Das Netzwerk ist definiert als , was bedeutet, dass nur damit verbundene Dienste kommunizieren können.
  • Geheimnisse: Sensible Daten wie Passwörter werden als Docker-Geheimnisse gespeichert, die als Dateien im Container gespeichert werden.
  • Gesundheitschecks: Dienste deklarieren Gesundheitschecks, so dass auf den Zustand warten kann. Nginx startet erst, nachdem die API gesund ist.
  • Static assets: Die Frontend-Build-Ausgabe wird direkt in Nginx eingepasst, sodass Nginx statische Dateien bedienen kann, ohne den Frontend-Dev-Server zu treffen.

Bereitstellung der Anwendung – Schritt für Schritt

Wenn die Compose-Datei und die Nginx-Konfiguration bereit sind, beinhaltet die Bereitstellung einige einfache Befehle: Erstens, stellen Sie sicher, dass alle Konfigurationsdateien vorhanden sind:

project/
├── docker-compose.yml
├── nginx/
│ └── nginx.conf
├── api/
│ └── .env.production
├── frontend/
│ └── build/
├── certs/
│ └── (fullchain.pem, privkey.pem)
└── secrets/
 └── db_password.txt

Dann laufen:

docker compose pull # pull latest images
docker compose up -d # start all services in background
docker compose ps # verify services are running
docker compose logs -f # tail logs for all services

Wenn alles erledigt ist, testen Sie die Anwendung, indem Sie Ihre Domain besuchen. Überprüfen Sie Nginx-Protokolle, um zu bestätigen, dass Anfragen korrekt angezeigt werden. Wenn Sie die Konfigurations- oder Umgebungsvariablen aktualisieren müssen, bearbeiten Sie die entsprechenden Dateien und führen Sie aus:

docker compose up -d --no-deps --build nginx # rebuild only nginx if config changed

Für Null-Downtime-Bereitstellungen sollten Sie blau-grün oder Rolling-Updates mit Compose -Funktion und Nginx Upstream-Gesundheitschecks verwenden.

Skalierung und Performance Tuning

Docker Compose macht es trivial, zustandslose Dienste wie die API zu skalieren:

docker compose up -d --scale api=3

Jetzt laufen drei Repliken des API-Containers. Nginx, konfiguriert mit dem Upstream-Block, verteilt automatisch Anfragen unter ihnen.

  • Aktivieren Sie die Gzip-Komprimierung in Nginx für textbasierte Antworten.
  • Set richtige Cache-Header für statische Assets (wie im Beispiel gezeigt).
  • Verwenden Sie ein CDN für die globale Lieferung von statischen Dateien.
  • Tune Nginx Worker Prozesse, um CPU-Kerne zu entsprechen:
  • Erhöhen Sie die Verbindungsgrenzen:

Stellen Sie bei Datenbanken sicher, dass Sie eine Verbindungspooling-Funktion in Ihrer API haben, und ziehen Sie die Verwendung von PgBouncer als Sidecar-Container in Betracht.

Problembehandlung bei gemeinsamen Problemen

Selbst bei einem gut strukturierten Setup können Dinge schief gehen. Hier sind häufige Fallstricke und wie man sie beheben kann:

  • Container kann einen anderen Dienst nicht mit Namen erreichen: Überprüfen Sie, ob sich beide Dienste im selben Docker-Netzwerk befinden.
  • Nginx gibt 502 Bad Gateway zurück: Der Upstream-Container läuft möglicherweise nicht oder hört nicht auf dem erwarteten Port.
  • Permission Errors with volumes: Dateien, die in Containern gespeichert werden, erben das Eigentum des Hosts. Verwenden Sie Benutzernamensräume oder legen Sie die -Direktive in Nginx und dem Servicecontainer fest.
  • SSL-Zertifikat nicht erneuern: Wenn Sie certbot standalone verwenden, stellen Sie sicher, dass die Ports 80 und 443 während der Erneuerung nicht von Nginx blockiert werden.
  • Umweltvariablen nicht geladen: Überprüfen Sie, ob sich die -Datei an der richtigen Stelle befindet, oder verwenden Sie die -Direktive richtig.

Best Practices für Sicherheit

Der Betrieb von Multicontainer-Anwendungen in der Produktion erfordert Wachsamkeit:

  • ] Führen Sie Container niemals als root aus, wenn nicht notwendig, verwenden Sie die -Direktive oder geben Sie eine in der Dockerdatei an.
  • Behalte Bilder auf dem neuesten Stand mit regelmäßigem Schwachstellen-Scannen.
  • Beschränken Sie die Netzwerkexposition: Setzen Sie nur die Reverse-Proxy-Ports für das Internet frei.
  • Verwenden Sie Secrets Management für Passwörter, API-Schlüssel und Token. Docker Secrets sind ein guter Anfang; für größere Setups sollten Sie HashiCorp Vault in Betracht ziehen.
  • Aktivieren Sie Docker Content Trust, um Bildsignaturen zu überprüfen.
  • Regelmäßig protokollieren und auditieren Containeraktivität mit oder einer zentralisierten Logging-Lösung wie ELK-Stack.
  • Ressourcenlimits in Ihrer Compose-Datei anwenden, um zu verhindern, dass ein einzelner Container andere aushungert:
services:
 api:
 deploy:
 resources:
 limits:
 cpus: '0.50'
 memory: 256M
 reservations:
 cpus: '0.25'
 memory: 128M

Diese Grenzen werden bei der Verwendung von Docker-Schwarm respektiert; für einfaches Komponieren werden sie mit FLT: 43 durchgesetzt (obwohl es besser ist, Schwarm oder K8s für die Produktionsorchestrierung zu verwenden).

Schlussfolgerung

Docker Compose und Nginx bilden zusammen eine leistungsstarke, skalierbare und wartbare Plattform für die Bereitstellung von Multicontainer-Webanwendungen. Indem Sie Ihren Stack in einer einzigen YAML-Datei definieren, erreichen Sie eine Umgebungsparität von der Entwicklung bis zur Produktion. Nginx bietet als Reverse-Proxy einen zentralen Punkt für SSL-Terminierung, Traffic-Routing, Load Balancing und Caching. Wir haben die wesentlichen Komponenten abgedeckt: Servicedefinitionen, Netzwerk, Volumes, Umgebungsvariablen, Nginx-Konfiguration mit Sicherheits- und Leistungsoptimierungen, Skalierungstipps und Fehlersuche. Mit dieser Grundlage sind Sie bereit, moderne containerisierte Anwendungen mit Vertrauen zu gestalten, bereitzustellen und zu betreiben.