Docker Networking - nginx: [emerg] Host nicht im Upstream gefunden


90

Ich habe kürzlich mit der Migration auf die Netzwerkfunktionen von Docker 1.9 und Docker-Compose 1.5 begonnen, um die Verwendung von Links zu ersetzen.

Bisher gab es bei Links keine Probleme mit der Verbindung von nginx zu meinem php5-fpm fastcgi-Server, der sich über Docker-Compose auf einem anderen Server in einer Gruppe befindet. Neu, wenn ich docker-compose --x-networking upmeine PHP-Fpm laufen lasse, starten Mongo- und Nginx-Container, aber Nginx wird sofort mit beendet[emerg] 1#1: host not found in upstream "waapi_php_1" in /etc/nginx/conf.d/default.conf:16

Wenn ich jedoch den Docker-Compose-Befehl erneut ausführe, während die PHP- und Mongo-Container ausgeführt werden (Nginx beendet), wird Nginx gestartet und funktioniert von da an einwandfrei.

Das ist meine docker-compose.ymlDatei:

nginx:
  image: nginx
  ports:
    - "42080:80"
  volumes:
    - ./config/docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro

php:
  build: config/docker/php
  ports:
    - "42022:22"
  volumes:
    - .:/var/www/html
  env_file: config/docker/php/.env.development

mongo:
  image: mongo
  ports:
    - "42017:27017"
  volumes:
    - /var/mongodata/wa-api:/data/db
  command: --smallfiles

Dies ist meine default.conffür Nginx:

server {
    listen  80;

    root /var/www/test;

    error_log /dev/stdout debug;
    access_log /dev/stdout;

    location / {
        # try to serve file directly, fallback to app.php
        try_files $uri /index.php$is_args$args;
    }

    location ~ ^/.+\.php(/|$) {
        # Referencing the php service host (Docker)
        fastcgi_pass waapi_php_1:9000;

        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;

        # We must reference the document_root of the external server ourselves here.
        fastcgi_param SCRIPT_FILENAME /var/www/html/public$fastcgi_script_name;

        fastcgi_param HTTPS off;
    }
}

Wie kann ich Nginx dazu bringen, mit nur einem einzigen Docker-Compose-Aufruf zu arbeiten?


3
Ich begegne dem auch. Ich bin nicht sicher, ob es sich um einen Fehler in der Erstellungsdatei oder um einen Fehler im Docker-Netzwerk selbst handelt.
27.

Antworten:


23

Es besteht die Möglichkeit, "volume_from" als Problemumgehung zu verwenden, bis die Funktion "abhängig_on" (siehe unten) eingeführt wird. Alles, was Sie tun müssen, ist, Ihre Docker-Compose-Datei wie folgt zu ändern:

nginx:
  image: nginx
  ports:
    - "42080:80"
  volumes:
    - ./config/docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
  volumes_from:
    - php

php:
  build: config/docker/php
  ports:
    - "42022:22"
  volumes:
    - .:/var/www/html
  env_file: config/docker/php/.env.development

mongo:
  image: mongo
  ports:
    - "42017:27017"
  volumes:
    - /var/mongodata/wa-api:/data/db
  command: --smallfiles

Eine große Einschränkung bei dem obigen Ansatz besteht darin, dass die PHP-Volumina Nginx ausgesetzt sind, was nicht erwünscht ist. Im Moment ist dies jedoch eine Docker-spezifische Problemumgehung, die verwendet werden könnte.

abhängige_auf Funktion Dies wäre wahrscheinlich eine futuristische Antwort. Da die Funktionalität in Docker noch nicht implementiert ist (ab 1.9)

Es gibt einen Vorschlag, "abhängige_on" in die neue Netzwerkfunktion von Docker einzuführen. Aber es gibt eine langen laufende Debatte über die gleichen @ https://github.com/docker/compose/issues/374 daher , sobald sie umgesetzt werden, könnte das Merkmal depends_on verwendet werden , um die Behälter Inbetriebnahme zu bestellen, aber bei der Moment müssten Sie auf eines der folgenden zurückgreifen:

  1. Nginx erneut versuchen, bis der PHP-Server hochgefahren ist - ich würde diesen vorziehen
  2. Verwenden Sie volums_from Workaround wie oben beschrieben - ich würde dies vermeiden, da das Volumen in unnötige Container gelangt.

3
Das hat es für mich nicht behoben.
Gijs

@Gijs Wenn Sie posten können, was Ihr genauer Fall ist und was nicht funktioniert hat, könnte jemand im Forum helfen.
Phani

4
volumen_von sind veraltet
Roma Rush

Ich bin dabei auf ein Problem in Azure App Service Docker Compose (Vorschau) gestoßen. Außerdem musste sichergestellt werden, dass alle links:in nginx enthaltenen Elemente denselben Namen wie der Dienst selbst - my-service:my-serviceoder in diesem Beispiel verwenden - mongo:mongo.
Greg

27

Dies kann mit der genannten depends_onRichtlinie gelöst werden, da sie jetzt (2016) implementiert ist:

version: '2'
  services:
    nginx:
      image: nginx
      ports:
        - "42080:80"
      volumes:
        - ./config/docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
      depends_on:
        - php

    php:
      build: config/docker/php
      ports:
        - "42022:22"
      volumes:
        - .:/var/www/html
      env_file: config/docker/php/.env.development
      depends_on:
        - mongo

    mongo:
      image: mongo
      ports:
        - "42017:27017"
      volumes:
        - /var/mongodata/wa-api:/data/db
      command: --smallfiles

Erfolgreich getestet mit:

$ docker-compose version
docker-compose version 1.8.0, build f3628c7

Weitere Details finden Sie in der Dokumentation .

Es gibt auch einen sehr interessanten Artikel zu diesem Thema: Steuern der Startreihenfolge in Compose


12

Sie können die Direktiven max_fails und fail_timeout von nginx festlegen, um anzugeben, dass nginx die x-Anzahl von Verbindungsanforderungen an den Container wiederholen soll, bevor ein Fehler auf der Nichtverfügbarkeit des Upstream-Servers auftritt.

Sie können diese beiden Zahlen entsprechend Ihrer Infrastruktur und Geschwindigkeit einstellen, mit der das gesamte Setup ausgeführt wird. Weitere Informationen zum Abschnitt " Integritätsprüfungen" finden Sie unter der folgenden URL: http://nginx.org/en/docs/http/load_balancing.html

Es folgt der Auszug aus http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server max_fails=number

Legt die Anzahl der erfolglosen Kommunikationsversuche mit dem Server fest, die in der durch den Parameter fail_timeout festgelegten Dauer stattfinden sollen, damit der Server für eine Dauer nicht verfügbar ist, die auch durch den Parameter fail_timeout festgelegt wird. Standardmäßig ist die Anzahl der erfolglosen Versuche auf 1 festgelegt. Der Wert Null deaktiviert die Abrechnung von Versuchen. Was als erfolgloser Versuch angesehen wird, wird durch die Anweisungen proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream und memcached_next_upstream definiert.

fail_timeout=time

Legt die Zeit fest, in der die angegebene Anzahl erfolgloser Kommunikationsversuche mit dem Server den Server als nicht verfügbar betrachten soll. und der Zeitraum, in dem der Server als nicht verfügbar angesehen wird. Standardmäßig ist der Parameter auf 10 Sekunden eingestellt.

Um genau zu sein, sollte Ihre geänderte Nginx-Konfigurationsdatei wie folgt lauten (dieses Skript geht davon aus, dass alle Container mindestens 25 Sekunden in Betrieb sind. Wenn nicht, ändern Sie bitte das Fail_timeout oder max_fails im folgenden Upstream-Abschnitt): Hinweis: Ich habe es nicht getan Testen Sie das Skript selbst, damit Sie es ausprobieren können!

upstream phpupstream {
   server waapi_php_1:9000 fail_timeout=5s max_fails=5;
}
server {
    listen  80;

    root /var/www/test;

    error_log /dev/stdout debug;
    access_log /dev/stdout;

    location / {
        # try to serve file directly, fallback to app.php
        try_files $uri /index.php$is_args$args;
    }

    location ~ ^/.+\.php(/|$) {
        # Referencing the php service host (Docker)
        fastcgi_pass phpupstream;

        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;

        # We must reference the document_root of the external server ourselves here.
        fastcgi_param SCRIPT_FILENAME /var/www/html/public$fastcgi_script_name;

        fastcgi_param HTTPS off;
    }
}

Gemäß dem folgenden Hinweis von Docker ( https://github.com/docker/docker.github.io/blob/master/compose/networking.md#update-containers ) ist es offensichtlich, dass die Wiederholungslogik für die Überprüfung Die Gesundheit der anderen Container liegt nicht in der Verantwortung des Dockers, sondern die Container sollten den Gesundheitscheck selbst durchführen.

Container aktualisieren

Wenn Sie eine Konfigurationsänderung an einem Dienst vornehmen und Docker-Compose ausführen, um ihn zu aktualisieren, wird der alte Container entfernt und der neue wird unter einer anderen IP-Adresse mit demselben Namen dem Netzwerk hinzugefügt. Laufende Container können diesen Namen nachschlagen und eine Verbindung zur neuen Adresse herstellen, aber die alte Adresse funktioniert nicht mehr.

Wenn Container Verbindungen zum alten Container haben, werden sie geschlossen. Es liegt in der Verantwortung eines Containers, diesen Zustand zu erkennen, den Namen erneut nachzuschlagen und die Verbindung wiederherzustellen.


3
Das wird nicht funktionieren. Lesen Sie die Einschränkung am Ende dieses Abschnitts in den Nginx-Dokumenten: "Wenn nur ein Server in einer Gruppe vorhanden ist, werden die Parameter max_fails, fail_timeout und slow_start ignoriert, und ein solcher Server wird niemals als nicht verfügbar angesehen."
Ferguzz

1
@Ferguzz das war ein schöner Fang. Um dieses Problem zu umgehen, können Sie zwei Alias-Einträge desselben Containers hinzufügen, um aus demselben Container eine Gruppe zu erstellen.
Phani

Als alternative Lösung habe ich in derselben Frage "volume_from" verwendet, um die Container zu verknüpfen und sie warten zu lassen, bis andere Container geladen sind. Das funktioniert bei mir.
Phani

7

Ich glaube, Nginx berücksichtigt den Docker-Resolver (127.0.0.11) nicht. Können Sie also bitte hinzufügen:

resolver 127.0.0.11

in Ihrer Nginx-Konfigurationsdatei?


Fügen Sie mehrere Resolver wieresolver 127.0.0.11 8.8.8.8;
Leonardo Chaia

Nein, da es in Round Robin abfragt, wie in den Dokumenten angegeben: Nameserver werden in Round-Robin-Weise abgefragt.
Bangalore

6

Wenn Sie so verloren sind, lesen Sie den letzten Kommentar. Ich habe eine andere Lösung erreicht.

Das Hauptproblem ist die Art und Weise, wie Sie die Dienstnamen benannt haben.

In diesem Fall docker-compose.ymlmüssen Sie sicherstellen, dass in der Datei nginx.confdie Zeile, die mit beginnt fastcgi_pass, denselben Namen wie der PHP-Dienst hat , wenn in Ihrem Fall der Dienst für PHP "API" oder ähnliches heißt . dhfastcgi_pass api:9000;


2

Hatte das gleiche Problem und löste es. Bitte fügen Sie die folgende Zeile zum Abschnitt docker-compose.yml nginx hinzu:

links:
  - php:waapi_php_1

Der Host im Abschnitt nginx config fastcgi_pass sollte in der Konfiguration docker-compose.yml nginx verknüpft sein.


2

Ich hatte das gleiche Problem, weil in meinem Netzwerk zwei Netzwerke definiert waren docker-compose.yml: ein Backend und ein Frontend.
Als ich das änderte, um Container im selben Standardnetzwerk auszuführen, funktionierte alles einwandfrei.


Dies ist weit davon entfernt, eine Antwort zu sein.
Dargmuesli

1

Zwei erwähnenswerte Dinge:

  • Verwenden derselben Netzwerkbrücke
  • Verwenden linkszum Hinzufügen von Hosts Resol

Mein Beispiel:

version: '3'
services:
  mysql:
    image: mysql:5.7
    restart: always
    container_name: mysql
    volumes:
      - ./mysql-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: tima@123
    network_mode: bridge
  ghost:
    image: ghost:2
    restart: always
    container_name: ghost
    depends_on:
      - mysql
    links:
      - mysql
    environment:
      database__client: mysql
      database__connection__host: mysql
      database__connection__user: root
      database__connection__password: xxxxxxxxx
      database__connection__database: ghost
      url: https://www.itsfun.tk
    volumes:
      - ./ghost-data:/var/lib/ghost/content
    network_mode: bridge
  nginx:
    image: nginx
    restart: always
    container_name: nginx
    depends_on:
      - ghost
    links:
      - ghost
    ports:
      - "80:80"
      - "443:443"
    volumes:
       - ./nginx/nginx.conf:/etc/nginx/nginx.conf
       - ./nginx/conf.d:/etc/nginx/conf.d
       - ./nginx/letsencrypt:/etc/letsencrypt
    network_mode: bridge

Wenn Sie keine spezielle Netzwerkbrücke angeben, verwenden alle dieselbe Standardbrücke.


1

Auf den ersten Blick habe ich übersehen, dass mein "Web" -Dienst nicht gestartet wurde. Deshalb konnte nginx keinen Host finden

web_1    | python3: can't open file '/var/www/app/app/app.py': [Errno 2] No such file or directory
web_1 exited with code 2
nginx_1  | [emerg] 1#1: host not found in upstream "web:4044" in /etc/nginx/conf.d/nginx.conf:2

Hey, ich habe das gleiche Problem. Meine Anwendung wird nicht ausgeführt, daher wird der gleiche Fehler angezeigt. Ich habe uwsgi-Datei als run.py in app.ini gesetzt, die die App hätte ausführen sollen, aber es passiert nicht
isrj5

0

Bei Links wird die Reihenfolge des Container-Starts erzwungen. Ohne Links können die Container in beliebiger Reihenfolge (oder wirklich alle auf einmal) starten.

Ich denke, das alte Setup hätte das gleiche Problem haben können, wenn der waapi_php_1Container nur langsam gestartet worden wäre.

Ich denke, um es zum Laufen zu bringen, könnten Sie ein Nginx-Einstiegspunkt-Skript erstellen, das abfragt und darauf wartet, dass der PHP-Container gestartet und bereit ist.

Ich bin mir nicht sicher, ob nginx eine Möglichkeit hat, die Verbindung zum Upstream automatisch erneut zu versuchen, aber wenn dies der Fall ist, wäre dies eine bessere Option.


Und wie mache ich Polling?
Attila Szeremi


0

Vielleicht ist die beste Wahl Behälter Probleme zu vermeiden Verknüpfung sind die Docker Networking - Funktionen

Damit dies funktioniert, erstellt Docker Einträge in den Dateien / etc / hosts für jeden Container aus den zugewiesenen Namen für jeden Container.

mit docker-compose --x-network -up ist so etwas wie [docker_compose_folder] - [service] - [incremental_number]

Um nicht von unerwarteten Änderungen dieser Namen abhängig zu sein, sollten Sie den Parameter verwenden

Containername

in Ihrer docker-compose.yml wie folgt:

php:
      container_name: waapi_php_1
      build: config/docker/php
      ports:
        - "42022:22"
      volumes:
        - .:/var/www/html
      env_file: config/docker/php/.env.development

Stellen Sie sicher, dass es sich um denselben Namen handelt, der in Ihrer Konfigurationsdatei für diesen Dienst zugewiesen ist. Ich bin mir ziemlich sicher, dass es bessere Möglichkeiten gibt, dies zu tun, aber es ist ein guter Ansatz, um anzufangen.


0

Meine Problemumgehung (nach langem Ausprobieren):

  • Um dieses Problem zu umgehen, musste ich den vollständigen Namen des 'Upstream'-Docker-Containers abrufen, der durch Ausführen docker network inspect my-special-docker-networkund Abrufen der vollständigen nameEigenschaft des Upstream-Containers als solcher ermittelt wurde:

    "Containers": {
         "39ad8199184f34585b556d7480dd47de965bc7b38ac03fc0746992f39afac338": {
              "Name": "my_upstream_container_name_1_2478f2b3aca0",
    
  • Verwenden Sie dies dann in der NGINX- my-network.local.confDatei im locationBlock der proxy_passEigenschaft: (Beachten Sie das Hinzufügen der GUID zum Containernamen):

    location / {
        proxy_pass http://my_upsteam_container_name_1_2478f2b3aca0:3000;
    

Im Gegensatz zu den bisher funktionierenden, aber jetzt kaputten:

    location / {
        proxy_pass http://my_upstream_container_name_1:3000

Die wahrscheinlichste Ursache ist eine kürzlich vorgenommene Änderung von Docker Compose im Standard-Benennungsschema für Container, wie hier aufgeführt .

Dies scheint für mich und mein Team bei der Arbeit mit den neuesten Versionen des Docker- nginxImages zu geschehen :

  • Ich habe geöffnet Probleme mit ihnen auf dem Docker / compose GitHub hier

0

(neu bei nginx) In meinem Fall war es ein falscher Ordnername

Für die Konfiguration

upstream serv {
    server ex2_app_1:3000;
}

Stellen Sie sicher, dass sich der App-Ordner im ex2-Ordner befindet:

ex2 / app / ...


0

Dieser Fehler erschien mir, weil mein php-fpmBild aktiviert cronwar und ich keine Ahnung habe, warum


-1

Fügen Sie den Linkabschnitt zu Ihrer Nginx-Containerkonfiguration hinzu.

Sie müssen den phpContainer für den nginxContainer sichtbar machen .

nginx:
  image: nginx
  ports:
    - "42080:80"
  volumes:
    - ./config/docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
  links:
    - php:waapi_php_1

1
Ich kenne Links, aber Docker hat sie in Version 1.9, die vor einer Woche veröffentlicht wurde, als veraltet markiert, um das Docker-Netzwerk zu nutzen. Ich hätte gerne eine Lösung, die dies nutzt, auch weil Links ein Problem mit zirkulären Links haben, das das Netzwerk nicht haben sollte.
Attila Szeremi

1
In CHANGELOG.md sehe ich nicht, dass linkes veraltet ist. Vermisse ich etwas
Nessuno

Das habe ich dort auch nicht gesehen; Wenn ich jedoch docker-compose --x-networking upmit in meinem definierten Links laufe docker-compose.yml, erhalte ich folgende eindeutige Warnung:WARNING: "nginx" defines links, which are not compatible with Docker networking and will be ignored. Future versions of Docker will not support links - you should remove them for forwards-compatibility.
Attila Szeremi

Ok, ich habe herausgefunden, wo die Abwertung ist. Die einzige Idee, die ich habe, ist: Befindet sich die docker-compose.ymlDatei in einem Ordner mit dem Namen waapi?
nessuno

Ja, es ist in einem Ordner namenswaapi
Attila Szeremi
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.