it-swarm.com.de

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

Ich habe vor kurzem mit der Migration zu Docker 1.9 und den Netzwerkfunktionen von Docker-Compose 1.5 begonnen, um die Verwendung von Links zu ersetzen.

Bisher gab es bei Links keine Probleme mit nginx, die Verbindung zu meinem php5-fpm fastcgi-Server auf einem anderen Server in einer Gruppe über Docker-Compose herzustellen. Wenn ich jedoch docker-compose --x-networking up laufe, werden meine PHP-fpm-, mongo- und nginx-Container hochgefahren, nginx wird jedoch sofort mit [emerg] 1#1: Host not found in upstream "waapi_php_1" in /etc/nginx/conf.d/default.conf:16 beendet.

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

Dies ist meine docker-compose.yml-Datei:

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 mein default.conf fü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 erreichen, dass Nginx nur mit einem einzigen Docker-Compose-Aufruf funktioniert?

59
Attila Szeremi

Es besteht die Möglichkeit, "volume_from" als Problemumgehung zu verwenden, bis die Funktion "_hunt_on" (siehe unten) eingeführt wird. Sie müssen lediglich Ihre Docker-Compose-Datei wie folgt ä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

Ein großer Nachteil bei dem obigen Ansatz ist, dass die Volumina von php Nginx ausgesetzt sind, was nicht erwünscht ist. Im Moment ist dies jedoch eine Docker-spezifische Problemumgehung, die verwendet werden könnte. 

depend_on feature Dies wäre wahrscheinlich eine futuristische Antwort. Weil die Funktionalität noch nicht in Docker implementiert ist (Stand 1.9)

Es gibt einen Vorschlag zur Einführung von "depend_on" in die von Docker eingeführte neue Netzwerkfunktion. Es gibt jedoch eine lange laufende Debatte über das gleiche @ https://github.com/docker/compose/issues/374 . Sobald das Feature implementiert ist, kann es daher dazu verwendet werden, den Container zu starten , aber im Moment müssten Sie eine der folgenden Möglichkeiten ergreifen:

  1. nginx erneut versuchen, bis der php-server läuft - ich würde diesen bevorzugen
  2. verwenden Sie volums_from Workaround wie oben beschrieben - ich würde dies wegen des Volumenverlusts in unnötige Container vermeiden. 
18
Phani

Dies kann mit der erwähnten depends_on-Direktive seit ihrer Implementierung (2016) gelöst werden:

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: Startreihenfolge in Compose steuern

13
czerasz

Sie können die Direktiven max_fails und fail_timeout von nginx festlegen, um anzugeben, dass der nginx die x-Anzahl der Verbindungsanforderungen an den Container erneut versuchen soll, bevor er auf der Nichtverfügbarkeit des Upstream-Servers fehlschlägt. 

Sie können diese beiden Zahlen entsprechend Ihrer Infrastruktur und der Geschwindigkeit anpassen, mit der die gesamte Einrichtung gestartet wird. Weitere Informationen zum Abschnitt "Gesundheitschecks" der folgenden URL finden Sie hier: http://nginx.org/de/docs/http/load_balancing.html

Es folgt der Auszug aus http://nginx.org/de/docs/http/ngx_http_upstream_module.html#servermax_fails=number

legt die Anzahl der fehlgeschlagenen Versuche fest, mit dem .__ zu kommunizieren. Server, der in der durch fail_timeout festgelegten Dauer erfolgen soll Parameter, der den Server als nicht verfügbar für eine festgelegte Dauer betrachtet durch den Parameter fail_timeout. Standardmäßig die Anzahl der nicht erfolgreichen Versuche ist auf 1 gesetzt. Der Nullwert deaktiviert die Abrechnung von Versuche. Was als ein erfolgloser Versuch angesehen wird, wird durch die .__ definiert. proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream- und memcached_next_upstream-Direktiven.

fail_timeout=time

legt die Zeit fest, in der die angegebene Anzahl von nicht erfolgreichen Versuche, mit dem Server zu kommunizieren, sollten die .__ berücksichtigen. Server nicht verfügbar; und der Zeitraum, auf dem sich der Server befindet als nicht verfügbar betrachtet. Der Parameter ist standardmäßig auf 10 eingestellt Sekunden.

Um genau zu sein, sollte Ihre modifizierte Nginx-Konfigurationsdatei wie folgt aussehen (dieses Skript geht davon aus, dass alle Container mindestens 25 Sekunden lang aktiv sind. Andernfalls ändern Sie im folgenden Upstream-Abschnitt den Parameter fail_timeout oder max_fails): Hinweis: I Ich habe das Skript nicht selbst getestet, also könnte man es ausprobieren!

upstream phpupstream {
   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äß der folgenden Anmerkung vom Docker ( https://github.com/docker/compose/blob/master/docs/networking.md ) ist es auch offensichtlich, dass die Wiederholungslogik zur Überprüfung des Zustands der Andere Container liegen nicht in der Verantwortung des Dockers, vielmehr sollten die Container die Gesundheitsprüfung selbst durchführen. 

Aktualisieren von Containern

Wenn Sie eine Konfigurationsänderung an einem Dienst vornehmen und docker-compose .__ ausführen. Zum Aktualisieren wird der alte Container entfernt und der neue verbindet sich unter einer anderen IP-Adresse, aber mit demselben Namen . Laufende Container können diesen Namen nachschlagen und sich mit .__ verbinden. die neue Adresse, aber die alte Adresse funktioniert nicht mehr.

Wenn Container mit dem alten Container verbunden sind, werden sie wird geschlossen. Es liegt in der Verantwortung eines Containers, dies zu erkennen Bedingung, suchen Sie den Namen erneut und verbinden Sie sich erneut.

8
Phani

Ich glaube, dass Nginx das Konto Docker Resolver (127.0.0.11) nicht berücksichtigt.

resolver 127.0.0.11

in deiner Nginx-Konfigurationsdatei?

4
Thomas Decaux

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

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

In diesem Fall müssen Sie, wenn in Ihrem docker-compose.yml der Dienst für php "api" oder so ähnlich heißt, sicherstellen, dass in der Datei nginx.conf die Zeile, die mit fastcgi_pass beginnt, denselben Namen wie der php-Dienst hat. das heißt fastcgi_pass api:9000;

2
julian

habe das gleiche problem bis es in einem docker-compose.yml zwei netzwerke gab: backend und frontend. Wenn alle Container in demselben Standardnetzwerk ausgeführt werden, funktioniert alles einwandfrei. 

1
smola

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

links:
  - php:waapi_php_1

Der Host in nginx config fastcgi_pass sollte in der docker-compose.yml nginx-Konfiguration verlinkt sein.

1
st0at

Mein Workaround (nach vielem Ausprobieren):

  • Um dieses Problem zu umgehen, musste ich den vollständigen Namen des Docker-Containers "upstream" abrufen, der durch Ausführen von docker network inspect my-special-docker-network und der vollständigen name-Eigenschaft des Upstream-Containers als solches ermittelt wurde:

    "Containers": {
         "39ad8199184f34585b556d7480dd47de965bc7b38ac03fc0746992f39afac338": {
              "Name": "my_upstream_container_name_1_2478f2b3aca0",
    
  • Dann wurde dies in der NGINX my-network.local.conf-Datei im location-Block der proxy_pass-Eigenschaft verwendet: (Beachten Sie das Hinzufügen von GUID zum Containernamen):

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

Im Gegensatz zu den vorher funktionierenden, aber jetzt kaputt:

    location / {
        proxy_pass http://my_upstream_container_name_1:3000

Die wahrscheinlichste Ursache ist eine kürzlich vorgenommene Änderung von Docker Compose in ihrem Standardnamensschema für Container, die in der Liste hier aufgeführt ist.

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

  • Ich habe Probleme mit ihnen im Docker/compose GitHub hier geöffnet.
0
arcadia_168

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

Für die Konfig

upstream serv {
    server ex2_app_1:3000;
}

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

ex2/app/...

0
vijeth.ag

Bei Links wird eine Reihenfolge beim Starten des Containers erzwungen. Ohne Verknüpfungen können die Container in beliebiger Reihenfolge (oder eigentlich alle gleichzeitig) gestartet werden.

Ich denke, das alte Setup hätte das gleiche Problem treffen können, wenn der waapi_php_1-Container langsam gestartet wurde.

Damit das funktioniert, können Sie ein Nginx-Entypoint-Skript erstellen, das abfragt und darauf wartet, dass der PHP-Container gestartet und fertig ist.

Ich bin nicht sicher, ob Nginx die Verbindung zum Upstream automatisch wiederherstellen kann, aber wenn dies der Fall ist, wäre dies eine bessere Option.

0
dnephin

Die beste Wahl, um Probleme mit der Verknüpfung von Containern zu vermeiden, sind die docker network -Funktionen

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

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

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

container_name

in Ihrem 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 diesem Dienst in Ihrer Konfigurationsdatei zugewiesen wurde. Ich bin mir ziemlich sicher, dass es bessere Wege gibt, dies zu tun, aber es ist ein guter Ansatz, um anzufangen.

0
JorelC

Zwei Dinge, die es zu erwähnen gilt:

  • Dieselbe Netzwerkbrücke verwenden
  • Mit links können Sie Hosts resol hinzufügen

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: [email protected]
    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, wird für alle dieselbe Standardbrücke verwendet.

0
NOZUONOHIGH

Sie müssen etwas wie Docker-Gen verwenden, um die Nginx-Konfiguration dynamisch zu aktualisieren, wenn Ihr Backend aktiv ist. 

Sehen:

Ich glaube, Nginx + (Premium-Version) enthält auch einen Auflösungsparameter ( http://nginx.org/de/docs/http/ngx_http_upstream_module.html#upstream )

0
Laurent B