Wie behebt man den Nginx-Fehler "Host Not Found In Upstream" in Docker?

Veröffentlicht 13. Oktober 2024

Problem: Nginx-Fehler "Host Not Found In Upstream"

Der Fehler "Host Not Found In Upstream" in Nginx kann bei der Verwendung von Docker-Containern auftreten. Dieser Fehler tritt auf, wenn Nginx den Upstream-Server in seiner Konfiguration nicht auflösen oder keine Verbindung zu ihm herstellen kann. Er resultiert oft aus Netzwerkproblemen oder falschen Einstellungen in der Docker-Umgebung.

Lösung des Nginx-Fehlers "Host Not Found In Upstream"

Verwendung von depends_on in docker-compose.yml

Die Anweisung depends_on in docker-compose.yml hilft bei der Verwaltung der Startreihenfolge von Containern. Sie weist Docker an, bestimmte Container vor anderen zu starten. Dies kann dazu beitragen, den Fehler "Host Not Found In Upstream" zu verhindern, indem sichergestellt wird, dass die erforderlichen Dienste laufen, bevor Nginx startet.

Um depends_on in Ihrer docker-compose.yml-Datei zu implementieren, fügen Sie es unter dem Nginx-Dienst hinzu und listen Sie die Dienste auf, auf die gewartet werden soll:

version: '3'
services:
  nginx:
    image: nginx
    depends_on:
      - php
    # Weitere Nginx-Konfiguration...

  php:
    image: php:fpm
    # PHP-Konfiguration...

Tipp: Überprüfen Sie die Bereitschaft des Dienstes

Beachten Sie, dass depends_on nur darauf wartet, dass der Container startet, nicht darauf, dass der Dienst im Inneren vollständig bereit ist. Für komplexere Setups sollten Sie die Verwendung von Healthchecks oder wait-for-it-Skripten in Betracht ziehen, um sicherzustellen, dass Dienste vollständig funktionsfähig sind, bevor Nginx startet.

Aktualisierung der Nginx-Konfiguration

Überprüfen Sie die fastcgi_pass-Anweisung in Ihrer Nginx-Konfiguration. Stellen Sie sicher, dass sie den korrekten Dienstnamen verwendet, wie er in Ihrer docker-compose.yml-Datei definiert ist. Wenn Ihr PHP-Dienst in docker-compose.yml als "php" benannt ist, sollte Ihr fastcgi_pass so aussehen:

fastcgi_pass php:9000;

Überprüfen Sie auch, ob die Dienstnamen in Ihrer Nginx-Konfiguration mit denen in Ihrer docker-compose.yml-Datei übereinstimmen. Nicht übereinstimmende Namen können den Fehler "Host Not Found In Upstream" verursachen.

Implementierung von wait-for-it-Skripten

Wait-for-it-Skripte sind Shell-Skripte, die den Start eines Containers verzögern, bis ein bestimmter Dienst bereit ist. Diese Skripte können dazu beitragen, den Fehler "Host Not Found In Upstream" zu verhindern, indem sie sicherstellen, dass Nginx erst startet, nachdem die erforderlichen Dienste vollständig betriebsbereit sind.

Um ein wait-for-it-Skript in Ihrem Docker-Setup zu verwenden:

  1. Fügen Sie das Skript zu Ihrem Projektverzeichnis hinzu.
  2. Aktualisieren Sie Ihr Dockerfile, um das Skript einzubinden.
  3. Ändern Sie den Befehl in Ihrer docker-compose.yml, um das wait-for-it-Skript zu verwenden:
nginx:
  image: nginx
  depends_on:
    - php
  command: ["./wait-for-it.sh", "php:9000", "--", "nginx", "-g", "daemon off;"]
  # Weitere Nginx-Konfiguration...

Dieser Ansatz bietet zusätzlichen Schutz vor Timing-Problemen, die den Fehler "Host Not Found In Upstream" verursachen können.

Beispiel: Benutzerdefiniertes Wait-Skript

Sie können ein benutzerdefiniertes Wait-Skript erstellen, das auf Ihre spezifischen Bedürfnisse zugeschnitten ist. Hier ist ein einfaches Beispiel in Bash:

#!/bin/bash
set -e

host="$1"
shift
cmd="$@"

until nc -z "$host" 9000; do
  >&2 echo "PHP-FPM ist nicht verfügbar - warte"
  sleep 1
done

>&2 echo "PHP-FPM ist bereit - führe Befehl aus"
exec $cmd

Speichern Sie dies als wait-for-php.sh in Ihrem Projektverzeichnis, machen Sie es ausführbar und aktualisieren Sie Ihre docker-compose.yml, um es zu verwenden:

nginx:
  image: nginx
  depends_on:
    - php
  command: ["./wait-for-php.sh", "php", "nginx", "-g", "daemon off;"]
  # Weitere Nginx-Konfiguration...

Alternative Lösungen zur Behebung des Nginx-Fehlers

Verwendung von Docker-Netzwerken

Die Erstellung von benutzerdefinierten Docker-Netzwerken kann helfen, den Fehler "Host Not Found In Upstream" zu beheben. Benutzerdefinierte Netzwerke ermöglichen es Containern, unter Verwendung ihrer Dienstnamen als Hostnamen zu kommunizieren.

Um ein benutzerdefiniertes Netzwerk zu erstellen:

  1. Definieren Sie das Netzwerk in Ihrer docker-compose.yml-Datei:
networks:
  myapp_network:
    driver: bridge
  1. Verbinden Sie Ihre Dienste mit diesem Netzwerk:
services:
  nginx:
    image: nginx
    networks:
      - myapp_network

  php:
    image: php:fpm
    networks:
      - myapp_network

Durch die Verwendung eines benutzerdefinierten Netzwerks verbessern Sie die Container-Kommunikation und reduzieren Probleme bei der Hostnamenauflösung.

Tipp: Netzwerk-Isolation

Erstellen Sie separate Netzwerke für verschiedene Teile Ihrer Anwendung, um die Sicherheit zu verbessern und den Datenverkehr zu steuern. Sie können beispielsweise ein Frontend-Netzwerk für Webserver und ein Backend-Netzwerk für Datenbanken haben:

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge

services:
  nginx:
    networks:
      - frontend
  php:
    networks:
      - frontend
      - backend
  database:
    networks:
      - backend

Implementierung von Healthchecks

Healthchecks in docker-compose.yml können den Fehler "Host Not Found In Upstream" verhindern, indem sie sicherstellen, dass ein Dienst bereit ist, bevor andere Dienste, die davon abhängen, gestartet werden.

Um Healthchecks hinzuzufügen:

  1. Fügen Sie einen Healthcheck in Ihrer docker-compose.yml für den PHP-Dienst hinzu:
services:
  php:
    image: php:fpm
    healthcheck:
      test: ["CMD", "php-fpm", "-t"]
      interval: 10s
      timeout: 5s
      retries: 3
  1. Aktualisieren Sie den Nginx-Dienst, um von der Gesundheit des PHP-Dienstes abhängig zu sein:
services:
  nginx:
    image: nginx
    depends_on:
      php:
        condition: service_healthy

Diese Konfiguration stellt sicher, dass Nginx erst startet, nachdem der PHP-Dienst bereit ist, Verbindungen anzunehmen, was die Wahrscheinlichkeit des Fehlers "Host Not Found In Upstream" reduziert.