Ich habe mit Docker und Docker-Compose herumgespielt und habe eine Frage.
Derzeit sieht meine docker-compose.yml folgendermaßen aus:
app:
image: myname/php-app
volumes:
- /var/www
environment:
<SYMFONY_ENVIRONMENT>: dev
web:
image: myname/nginx
ports:
- 80
links:
- app
volumes_from:
- app
Die App enthält php-fpm auf Port 9000 und meinen Anwendungscode. Das Web ist nginx mit ein paar Konfigurationsteilen.
Dies funktioniert wie erwartet. Um Nginx jedoch mit PHP-FPM zu verbinden, habe ich diese Zeile:
fastcgi_pass app:9000;
Wie kann ich das effektiv skalieren? Wenn ich beispielsweise einen Nginx-Container, aber drei App-Container ausführen möchte, dann werde ich sicherlich drei PHP-FPM-Instanzen haben, die alle versuchen, auf Port 9000 zu lauschen.
Wie kann ich jede PHP-FPM-Instanz auf einem anderen Port haben und trotzdem jederzeit wissen, wo sie sich in meiner Nginx-Konfiguration befinden?
Gehe ich falsch vor?
Danke!
Antwort1
Eine Lösung besteht darin, Ihrer Docker-Compose-Datei zusätzliche PHP-FPM-Instanzen hinzuzufügen und dann wie in den anderen Antworten erwähnt einen Nginx-Upstream zu verwenden, um den Lastenausgleich zwischen ihnen durchzuführen. Dies wird in diesem Beispiel-Docker-Compose-Repo durchgeführt:https://github.com/iamyojimbo/docker-nginx-php-fpm/blob/master/nginx/nginx.conf#L137
upstream php {
#If there's no directive here, then use round_robin.
#least_conn;
server dockernginxphpfpm_php1_1:9000;
server dockernginxphpfpm_php2_1:9000;
server dockernginxphpfpm_php3_1:9000;
}
Dies ist nicht wirklich ideal, da beim Hoch- oder Herunterskalieren die Nginx-Konfiguration und die Datei docker-compose.yml geändert werden müssen.
Beachten Sie, dass Port 9000 intern für den Container und nicht für Ihren tatsächlichen Host ist. Es spielt also keine Rolle, dass Sie mehrere PHP-FPM-Container auf Port 9000 haben.
Docker hat Tutum diesen Herbst übernommen. Sie haben eine Lösung, die einen HAProxy-Container mit ihrer API kombiniert, um die Load-Balancer-Konfiguration automatisch an die laufenden Container anzupassen, deren Lastenausgleich es vornimmt. Das ist eine gute Lösung. Dann verweist nginx auf den Hostnamen, der dem Load Balancer zugewiesen ist. Vielleicht wird Docker diese Art von Lösung nach der Übernahme von Tutum noch weiter in seine Tools integrieren. Hier gibt es einen Artikel dazu:https://web.archive.org/web/20160628133445/https://support.tutum.co/support/solutions/articles/5000050235-load-balancing-a-web-service
Tutum ist derzeit ein kostenpflichtiger Dienst. Rancher ist ein Open-Source-Projekt, das eine ähnliche Lastausgleichsfunktion bietet. Sie haben auch eine „rancher-compose.yml“, mit der der Lastausgleich und die Skalierung der in der docker-compose.yml eingerichteten Dienste definiert werden können. http://rancher.com/der-magische-moment-wenn-container-load-balancing-auf-service-discovery-trifft/ http://docs.rancher.com/rancher/concepts/#load-balancer
UPDATE 2017/03/06: Ich habe ein Projekt namensVerriegelungdas mit Docker zusammenarbeitet, um die Nginx-Konfiguration automatisch zu aktualisieren und neu zu starten. Siehe auch @iwaseatenbyagrue'sAntwortwelches zusätzliche Ansätze hat.
Antwort2
Obwohl dieser Beitrag aus dem Jahr 2015 stammt und ich das Gefühl habe, dass ich ihn wiederbelebe (tut mir leid, Community), halte ich es zum jetzigen Zeitpunkt für sinnvoll, Folgendes hinzuzufügen:
Heutzutage (und da Kubernetes erwähnt wurde) können Sie, wenn Sie mit Docker arbeiten, Kubernetes oder Docker Swarm sehr einfach verwenden, um dieses Problem zu lösen. Beide Orchestratoren nehmen Ihre Docker-Knoten auf (ein Knoten = ein Server mit Docker darauf) und Sie können Dienste auf ihnen bereitstellen und sie verwalten Port-Herausforderungen für Sie mithilfe von Overlay-Netzwerken.
Da ich mich mit Docker Swarm besser auskenne, können Sie dieses Problem folgendermaßen angehen (vorausgesetzt, Sie haben einen einzelnen Docker-Knoten):
Initialisieren Sie den Schwarm:
docker swarm init
Wechseln Sie mit cd in das Stammverzeichnis Ihres Projekts
cd some/project/root
Erstellen Sie einen Swarm-Stack aus Ihrer docker-compose.yml (anstatt docker-compose zu verwenden):
docker stack deploy -c docker-compose.yml myApp
Dadurch wird ein Docker-Swarm-Service-Stack namens „myApp“ erstellt, der die Ports für Sie verwaltet. Das bedeutet: Sie müssen Ihrem php-fpm-Service in Ihrer Docker-Compose-Datei nur eine „Port: 9000:9000“-Definition hinzufügen und können dann den php-fpm-Service hochskalieren, beispielsweise auf 3 Instanzen, während der Swarm die Anfragen automatisch zwischen den drei Instanzen ausgleicht, ohne dass weitere Arbeit erforderlich ist.
Antwort3
Sie können einen Upstream verwenden, um mehrere Backends zu definieren, wie hier beschrieben:
https://stackoverflow.com/questions/5467921/wie-man-fastcgi-next-upstream-in-nginx verwendet
Sie möchten die Konfiguration auch immer dann aktualisieren, wenn neue Backends ausfallen/in Betrieb genommen werden, und zwar mit etwas wie:
Antwort4
Ein anderer Ansatz könnte darin bestehen, sich mit etwas wieKonsul-Vorlage.
Und natürlich irgendwannKubernetesmuss möglicherweise erwähnt werden.
Sie können jedoch auch einen etwas sparsameren Ansatz mit Schnur und Klebeband in Betracht ziehen, indem Sie sich anschauen, was die Nutzung von Docker-Ereignissen für Sie leisten könnte (führen Sie es docker events --since 0
für ein kurzes Beispiel aus).
Es wäre relativ einfach, ein Skript zu haben, das diese Ereignisse betrachtet (unter Berücksichtigung, dass mehrere Client-Pakete verfügbar sind, darunter für Python, Go usw.), eine Konfigurationsdatei ändert und nginx neu lädt (d. h. unter Verwendung des Consul-Template-Ansatzes, aber ohne die Notwendigkeit von Consul).
Um jedoch auf Ihre ursprüngliche Prämisse zurückzukommen: Solange Ihre PHP-FPM-Container mit ihrem eigenen Netzwerk gestartet werden (also nicht das Netzwerk eines anderen Containers, wie etwa des Nginx-Containers, gemeinsam nutzen), können so viele Container wie Sie möchten auf Port 9000 lauschen – da sie über IPs pro Container verfügen, gibt es kein Problem mit „Kollisionen“ der Ports.
Wie Sie dies skalieren, hängt wahrscheinlich von Ihrem endgültigen Ziel/Anwendungsfall ab, aber Sie könnten beispielsweise in Erwägung ziehen, HAproxy zwischen nginx und Ihren php-fpm-Knoten zu platzieren. Dies könnte Ihnen beispielsweise ermöglichen, einfach einen Bereich docker network
für Ihre php-fpm-Server zu benennen (und möglicherweise einen zu erstellen) (z. B. 172.18.0.0/24) und HAproxy so zu konfigurieren, dass es versucht, jede IP innerhalb dieses Bereichs als Backend zu verwenden. Da HAproxy über Integritätsprüfungen verfügt, kann es schnell erkennen, welche Adressen aktiv sind, und diese nutzen.
Sehenhttps://stackoverflow.com/questions/1358198/nginx-removing-upstream-servers-from-poolfür eine Diskussion darüber, wie nginx im Vergleich zu haproxy mit Upstreams umgeht.
Sofern Sie hierfür kein dediziertes Docker-Netzwerk verwenden,könnteSie müssen für Ihre PHP-FPM-Knoten eine manuelle IP-Verwaltung durchführen.