Docker Networking - nginx: [emerg] host nie został znaleziony w upstream

99

Niedawno rozpocząłem migrację do funkcji sieciowych Docker 1.9 i Docker-Compose 1.5, aby zastąpić użycie linków.

Do tej pory z linkami nie było problemów z połączeniem nginx z moim serwerem fastcgi php5-fpm znajdującym się na innym serwerze w jednej grupie przez docker-compose. Niedawno jednak, kiedy uruchamiam docker-compose --x-networking upmoje kontenery php-fpm, mongo i nginx, jednak nginx kończy pracę natychmiast po[emerg] 1#1: host not found in upstream "waapi_php_1" in /etc/nginx/conf.d/default.conf:16

Jeśli jednak uruchomię ponownie polecenie docker-compose, gdy kontenery php i mongo są uruchomione (wyjście z nginx), nginx uruchamia się i od tego momentu działa dobrze.

To jest mój docker-compose.ymlplik:

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

To jest moje default.confdla 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;
    }
}

Jak sprawić, by nginx działał tylko z jednym wywołaniem docker-compose?

Attila Szeremi
źródło
3
Ja też to spotykam. Nie jestem pewien, czy jest to błąd w pliku redagowania, czy błąd w samej sieci Dockera.
jrdn

Odpowiedzi:

26

Istnieje możliwość użycia „volume_from” jako obejścia do czasu wprowadzenia funkcji depend_on (omówionej poniżej). Wszystko, co musisz zrobić, to zmienić plik docker-compose, jak poniżej:

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

Jednym dużym zastrzeżeniem w powyższym podejściu jest to, że woluminy php są narażone na działanie nginx, co nie jest pożądane. Ale w tej chwili jest to jedno obejście specyficzne dla platformy Docker, którego można użyć.

Funkcja depends_on To prawdopodobnie byłaby futurystyczna odpowiedź. Ponieważ funkcja nie została jeszcze zaimplementowana w Dockerze (od 1.9)

Istnieje propozycja wprowadzenia „depends_on” w nowej funkcji sieciowej wprowadzonej przez Docker. Ale trwa długo trwająca debata na temat tego samego @ https://github.com/docker/compose/issues/374.W związku z tym po wdrożeniu funkcja depends_on może zostać użyta do zamówienia uruchomienia kontenera, ale w tej chwili musiałbyś uciec się do jednego z następujących:

  1. spraw, aby nginx ponawiał próbę, aż serwer php zostanie uruchomiony - wolałbym ten
  2. użyj obejścia volums_from jak opisano powyżej - unikałbym tego ze względu na wyciek objętości do niepotrzebnych pojemników.
Phani
źródło
3
To mi nie pomogło.
Gijs,
@Gijs, jeśli możesz opublikować swój dokładny przypadek, a co nie zadziałało, ktoś mógłby pomóc na forum.
Phani
4
tomy_from są przestarzałe
Roma Rush
Wystąpił problem w usłudze Azure App Service Docker Compose (wersja zapoznawcza) z tym. Musiałem również upewnić się, że każdy, links:który zawarłem w nginx, używał tej samej nazwy, co sama usługa, jak - my-service:my-servicew tym przykładzie - mongo:mongo.
greg
29

Można to rozwiązać za pomocą wspomnianej depends_ondyrektywy, ponieważ została ona wdrożona teraz (2016):

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

Pomyślnie przetestowano z:

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

Więcej szczegółów znajdziesz w dokumentacji .

Jest też bardzo ciekawy artykuł poświęcony temu tematowi: Kontrolowanie kolejności uruchamiania w Compose

czerasz
źródło
12

Możesz ustawić dyrektywy max_fails i fail_timeout nginx, aby wskazać, że nginx powinien ponawiać x liczbę żądań połączenia do kontenera, zanim zakończy się niepowodzeniem w przypadku niedostępności serwera nadrzędnego.

Możesz dostroić te dwie liczby zgodnie ze swoją infrastrukturą i szybkością, z jaką nadchodzi cała konfiguracja. Więcej informacji na temat sekcji dotyczącej kontroli stanu można znaleźć pod poniższym adresem URL: http://nginx.org/en/docs/http/load_balancing.html

Poniżej znajduje się fragment z http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server max_fails=number

ustawia liczbę nieudanych prób komunikacji z serwerem, które powinny mieć miejsce w czasie określonym przez parametr fail_timeout, aby uznać, że serwer jest niedostępny przez czas określony również przez parametr fail_timeout. Domyślnie liczba nieudanych prób jest ustawiona na 1. Wartość zero wyłącza rozliczanie prób. To, co jest uważane za nieudaną próbę, jest definiowane przez dyrektywy proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream i memcached_next_upstream.

fail_timeout=time

ustawia czas, przez jaki ma nastąpić określona liczba nieudanych prób komunikacji z serwerem, aby uznać serwer za niedostępny; oraz okres czasu, przez który serwer będzie uważany za niedostępny. Domyślnie parametr jest ustawiony na 10 sekund.

Aby być precyzyjnym, twój zmodyfikowany plik konfiguracyjny nginx powinien wyglądać następująco (ten skrypt zakłada, że ​​wszystkie kontenery są wydłużone o co najmniej 25 sekund, jeśli nie, zmień fail_timeout lub max_fails w poniższej sekcji upstream): Uwaga: nie samodzielnie przetestuj skrypt, więc możesz spróbować!

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;
    }
}

Ponadto, zgodnie z następującą uwagą od docker ( https://github.com/docker/docker.github.io/blob/master/compose/networking.md#update-containers ), jest oczywiste, że logika ponawiania sprawdzania Docker nie ponosi odpowiedzialności za stan innych kontenerów i raczej kontenery powinny samodzielnie przeprowadzić kontrolę stanu.

Aktualizowanie kontenerów

Jeśli dokonasz zmiany konfiguracji w usłudze i uruchomisz docker-compose w celu jej aktualizacji, stary kontener zostanie usunięty, a nowy dołączy do sieci pod innym adresem IP, ale o tej samej nazwie. Uruchomione kontenery będą mogły wyszukać tę nazwę i połączyć się z nowym adresem, ale stary adres przestanie działać.

Jeśli jakiekolwiek kontenery mają otwarte połączenia ze starym kontenerem, zostaną zamknięte. Obowiązkiem kontenera jest wykrycie tego stanu, ponowne sprawdzenie nazwy i ponowne połączenie.

Phani
źródło
3
To nie zadziała. przeczytaj ostrzeżenie na końcu tej sekcji w dokumentacji nginx: "Jeśli w grupie jest tylko jeden serwer, parametry max_fails, fail_timeout i slow_start są ignorowane, a taki serwer nigdy nie będzie uważany za niedostępny."
Ferguzz,
1
@Ferguzz, to był niezły chwyt. Aby obejść ten problem, możesz dodać dwa wpisy aliasów tego samego kontenera, aby utworzyć grupę z tego samego kontenera.
Phani,
Jako alternatywne rozwiązanie, podałem w tym samym pytaniu użycie „volume_from” do połączenia kontenerów i sprawienia, by czekały, aż załadują się inne kontenery. To działa dla mnie.
Phani,
7

Uważam, że Nginx nie bierze pod uwagę programu rozpoznawania nazw Docker (127.0.0.11), więc proszę, czy możesz spróbować dodać:

resolver 127.0.0.11

w twoim pliku konfiguracyjnym nginx?

Thomas Decaux
źródło
Dodaj wiele resolverów, takich jakresolver 127.0.0.11 8.8.8.8;
Leonardo Chaia
1
Nie, ponieważ będzie wykonywać zapytania w trybie okrężnym, jak określono w dokumentacji: Zapytania do serwerów nazw są wykonywane w trybie okrężnym.
dalore
6

Jeśli jesteś tak zagubiony, przeczytaj ostatni komentarz. Osiągnąłem inne rozwiązanie.

Głównym problemem jest sposób nadawania nazw usługom.

W tym przypadku, jeśli twoja docker-compose.ymlusługa dla php nazywa się "api" lub coś w tym stylu, musisz upewnić się, że w pliku nginx.confwiersz zaczynający się od fastcgi_passma taką samą nazwę jak usługa php. to znaczyfastcgi_pass api:9000;

juliański
źródło
3

Miałem ten sam problem, ponieważ w moim zdefiniowano dwie sieci docker-compose.yml: jeden backend i jeden frontend.
Kiedy zmieniłem to, aby uruchamiać kontenery w tej samej domyślnej sieci, wszystko zaczęło działać dobrze.

smola
źródło
To jest dalekie od odpowiedzi.
dargmuesli
2

Miałem ten sam problem i rozwiązałem go. Dodaj następujący wiersz do sekcji docker-compose.yml nginx:

links:
  - php:waapi_php_1

Host w sekcji fastcgi_pass konfiguracji nginx powinien być połączony w konfiguracji docker-compose.yml nginx.

st0at
źródło
1

Warto wspomnieć o dwóch rzeczach:

  • Korzystanie z tego samego mostu sieciowego
  • Używanie linksdo dodawania hostów resol

Mój przykład:

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

Jeśli nie określisz specjalnego mostu sieciowego, wszystkie będą używać tego samego domyślnego.

NOZUONOHIGH
źródło
1

Na pierwszy rzut oka przegapiłem, że moja usługa „sieciowa” tak naprawdę się nie uruchomiła, dlatego nginx nie mógł znaleźć żadnego hosta

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
Alveona
źródło
hej mam ten sam problem. Moja aplikacja nie działa, więc pojawia się ten sam błąd. Umieściłem plik uwsgi jako run.py w app.ini, który powinien uruchomić aplikację, ale tak się nie dzieje
isrj5
0

W przypadku linków wymuszana jest kolejność uruchamiania kontenera. Bez linków kontenery mogą uruchamiać się w dowolnej kolejności (lub naprawdę wszystkie na raz).

Myślę, że stara konfiguracja mogła napotkać ten sam problem, jeśli plik waapi_php_1 kontener uruchamiał się wolno.

Myślę, że aby to działało, możesz stworzyć skrypt punktu wejścia nginx, który sonduje i czeka, aż kontener php zostanie uruchomiony i gotowy.

Nie jestem pewien, czy nginx ma jakikolwiek sposób na ponowienie próby połączenia z nadrzędnym automatycznie, ale jeśli tak, to byłaby lepsza opcja.

dnefina
źródło
Jak mam odpytywać?
Attila Szeremi
0

Być może najlepszym rozwiązaniem pozwalającym uniknąć problemów z łączeniem kontenerów jest sieć Dockera funkcje

Ale żeby to zadziałało, docker tworzy wpisy w / etc / hosts dla każdego kontenera z przypisanych nazw do każdego kontenera.

z docker-compose --x-networking -up to coś w rodzaju [docker_compose_folder] - [usługa] - [inckremental_number]

Aby nie polegać na nieoczekiwanych zmianach tych nazw, należy użyć parametru

nazwa_kontenera

w twoim docker-compose.yml w następujący sposób:

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

Upewnij się, że jest to ta sama nazwa przypisana w pliku konfiguracyjnym dla tej usługi. Jestem prawie pewien, że istnieją lepsze sposoby, aby to zrobić, ale na początek jest to dobre podejście.

JorelC
źródło
0

Moje obejście (po wielu próbach i błędach):

  • Aby obejść ten problem, musiałem uzyskać pełną nazwę kontenera Docker `` upstream '', znalezioną przez uruchomienie docker network inspect my-special-docker-networki pobranie pełnej namewłaściwości kontenera wyższego rzędu:

    "Containers": {
         "39ad8199184f34585b556d7480dd47de965bc7b38ac03fc0746992f39afac338": {
              "Name": "my_upstream_container_name_1_2478f2b3aca0",
    
  • Następnie użyłem tego w my-network.local.confpliku NGINX w locationbloku proxy_passwłaściwości: (Zwróć uwagę na dodanie identyfikatora GUID do nazwy kontenera):

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

W przeciwieństwie do poprzednio działającego, ale teraz zepsutego:

    location / {
        proxy_pass http://my_upstream_container_name_1:3000

Najbardziej prawdopodobną przyczyną jest niedawna zmiana w Docker Compose w ich domyślnym schemacie nazewnictwa kontenerów, jak wymieniono tutaj .

Wydaje się, że dzieje się tak w przypadku mnie i mojego zespołu w pracy z najnowszymi wersjami obrazu platformy Docker nginx:

  • Otworzyłem problemy z nimi w docker / compose GitHub tutaj
arcadia_168
źródło
0

(nowy w nginx) W moim przypadku była to zła nazwa folderu

W przypadku config

upstream serv {
    server ex2_app_1:3000;
}

upewnij się, że folder aplikacji znajduje się w folderze ex2:

ex2 / app / ...

vijeth.ag
źródło
0

ten błąd pojawił się, ponieważ mój php-fpmobraz jest włączony croni nie mam pojęcia, dlaczego

Ruan Nawe
źródło
0

Mój problem polegał na tym, że zapomniałem podać alias sieciowy w docker-compose.yml w php-fpm

    networks:
      - u-online

To działa dobrze!

version: "3"
services:

  php-fpm:
    image: php:7.2-fpm
    container_name: php-fpm
    volumes:           
      - ./src:/var/www/basic/public_html
    ports:
      - 9000:9000
    networks:
      - u-online
      
  nginx: 
    image: nginx:1.19.2
    container_name: nginx   
    depends_on:
      - php-fpm       
    ports:
      - "80:8080"
      - "443:443"
    volumes:
      - ./docker/data/etc/nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
      - ./docker/data/etc/nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./src:/var/www/basic/public_html
    networks:
      - u-online

#Docker Networks
networks:
  u-online:
    driver: bridge
Юрий Светлов
źródło
-1

Dodaj sekcję linków do konfiguracji kontenera nginx.

Musisz sprawić, by phpkontener był widoczny dla nginxkontenera.

nginx:
  image: nginx
  ports:
    - "42080:80"
  volumes:
    - ./config/docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
  links:
    - php:waapi_php_1
nessuno
źródło
1
Wiem o linkach, ale Docker oznaczył je jako przestarzałe w wersji 1.9, która wyszła tydzień temu, na korzyść korzystania z sieci Dockera. Chciałbym rozwiązania, które to wykorzystuje, częściowo dlatego, że łącza mają problem z łączeniem cyklicznym, którego nie powinny mieć sieci.
Attila Szeremi
1
W CHANGELOG.md nie widzę linkwycofania. Czy coś mi brakuje?
nessuno
Tam też tego nie widziałem; jednak kiedy uruchamiam docker-compose --x-networking upz linkami zdefiniowanymi w moim docker-compose.yml, otrzymuję wyraźne ostrzeżenie: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, znalazłem, gdzie jest wycofanie. Jedyny pomysł, jaki mam, to: czy docker-compose.ymlplik znajduje się w folderze o nazwie waapi?
nessuno
Tak, jest w folderze o nazwiewaapi
Attila Szeremi