Docker Networking - nginx: host [emerg] non trovato in upstream


99

Di recente ho iniziato la migrazione alle funzionalità di rete di Docker 1.9 e Docker-Compose 1.5 per sostituire utilizzando i collegamenti.

Finora con i collegamenti non ci sono stati problemi con nginx che si connette al mio server php5-fpm fastcgi situato in un server diverso in un gruppo tramite docker-compose. Di recente però quando docker-compose --x-networking upeseguo i miei contenitori php-fpm, mongo e nginx si avviano, tuttavia nginx si chiude immediatamente con[emerg] 1#1: host not found in upstream "waapi_php_1" in /etc/nginx/conf.d/default.conf:16

Tuttavia, se eseguo nuovamente il comando docker-compose mentre i contenitori php e mongo sono in esecuzione (uscita da nginx), nginx si avvia e da quel momento in poi funziona correttamente.

Questo è il mio docker-compose.ymlfile:

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

Questo è il mio default.confper 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;
    }
}

Come posso far funzionare nginx con una sola chiamata docker-compose?


3
Sto riscontrando anche questo. Non sono sicuro che si tratti di un errore con il file di composizione o di un bug con la stessa rete docker.
— jrdn

Risposte:


26

C'è la possibilità di utilizzare "volumi_from" come soluzione alternativa fino a quando non viene introdotta la funzione depend_on (discussa di seguito). Tutto quello che devi fare è cambiare il tuo file docker-compose come di seguito:

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

Un grande avvertimento nell'approccio di cui sopra è che i volumi di php sono esposti a nginx, il che non è desiderato. Ma al momento questa è una soluzione alternativa specifica per finestra mobile che potrebbe essere utilizzata.

Funzionalità dipende_on Questa probabilmente sarebbe una risposta futuristica. Perché la funzionalità non è ancora implementata in Docker (a partire dalla 1.9)

C'è una proposta per introdurre "depend_on" nella nuova funzionalità di rete introdotta da Docker. Ma c'è un lungo dibattito sullo stesso @ https://github.com/docker/compose/issues/374 Quindi, una volta implementata, la funzione depend_on potrebbe essere usata per ordinare l'avvio del container, ma al momento, dovresti ricorrere a uno dei seguenti:

  1. fai riprovare nginx fino a quando il server php non è attivo - preferirei questo
  2. utilizzare volums_from soluzione alternativa come descritto sopra: eviterei di usarlo, a causa della perdita di volume in contenitori non necessari.

3
Questo non ha risolto il problema per me.
— Gijs

@Gijs se puoi pubblicare qual è il tuo caso esatto e cosa non ha funzionato, qualcuno potrebbe aiutarti sul forum.
— Phani

4
i volumi_from sono deprecati
— Roma Rush

Ho riscontrato un problema nel servizio app di Azure Docker Compose (anteprima) con questo. links:Dovevo anche assicurarmi che tutti quelli che includevo in nginx usassero lo stesso nome del servizio stesso come - my-service:my-serviceo in questo esempio - mongo:mongo.
— greg

29

Questo può essere risolto con la depends_ondirettiva citata poiché è implementata ora (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

Testato con successo con:

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

Trova maggiori dettagli nella documentazione .

C'è anche un articolo molto interessante dedicato a questo argomento: Controllo dell'ordine di avvio in Compose


12

È possibile impostare le direttive max_fails e fail_timeout di nginx per indicare che nginx deve ritentare il numero x di richieste di connessione al contenitore prima di fallire sull'indisponibilità del server upstream.

Puoi regolare questi due numeri in base alla tua infrastruttura e alla velocità con cui l'intera configurazione sta arrivando. Puoi leggere maggiori dettagli sulla sezione dei controlli di integrità dell'URL seguente: http://nginx.org/en/docs/http/load_balancing.html

Di seguito è riportato l'estratto da http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server max_fails=number

imposta il numero di tentativi di comunicazione con il server non riusciti che dovrebbero verificarsi nella durata impostata dal parametro fail_timeout per considerare il server non disponibile per una durata impostata anche dal parametro fail_timeout. Per impostazione predefinita, il numero di tentativi non riusciti è impostato su 1. Il valore zero disabilita la contabilità dei tentativi. Ciò che è considerato un tentativo non riuscito è definito dalle direttive proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream e memcached_next_upstream.

fail_timeout=time

imposta il tempo durante il quale il numero specificato di tentativi di comunicazione con il server non riusciti dovrebbe accadere per considerare il server non disponibile; e il periodo di tempo in cui il server sarà considerato non disponibile. Per impostazione predefinita, il parametro è impostato su 10 secondi.

Per essere precisi, il tuo file di configurazione nginx modificato dovrebbe essere il seguente (questo script presume che tutti i contenitori siano attivi di almeno 25 secondi, in caso contrario, modifica fail_timeout o max_fails nella sezione a monte sotto): Nota: non l'ho fatto prova personalmente lo script, così potresti provarlo!

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

Inoltre, come da nota seguente da docker ( https://github.com/docker/docker.github.io/blob/master/compose/networking.md#update-containers ), è evidente che la logica di ripetizione del controllo lo stato di salute degli altri container non è responsabilità del dock e piuttosto i container dovrebbero fare il controllo di integrità da soli.

Aggiornamento dei contenitori

Se apporti una modifica alla configurazione di un servizio ed esegui docker-compose per aggiornarlo, il vecchio contenitore verrà rimosso e il nuovo si unirà alla rete con un indirizzo IP diverso ma con lo stesso nome. I contenitori in esecuzione potranno cercare quel nome e connettersi al nuovo indirizzo, ma il vecchio indirizzo smetterà di funzionare.

Se alcuni contenitori hanno connessioni aperte al vecchio contenitore, verranno chiusi. È responsabilità del container rilevare questa condizione, cercare di nuovo il nome e ricollegarsi.


3
Questo non funzionerà. leggere l'avvertenza alla fine di questa sezione nei documenti di nginx: "Se c'è un solo server in un gruppo, i parametri max_fails, fail_timeout e slow_start vengono ignorati e tale server non sarà mai considerato non disponibile."
— Ferguzz

1
@Ferguzz che è stata una bella cattura. Come soluzione alternativa, puoi aggiungere due voci alias dello stesso contenitore per creare un gruppo dallo stesso contenitore.
— Phani

Come soluzione alternativa, nella stessa domanda ho fornito l'uso di "volumi_from" per collegare i contenitori e farli attendere fino al caricamento di altri contenitori. Questo sta funzionando per me.
— Phani

7

Credo che Nginx non prenda in considerazione il resolver Docker (127.0.0.11), quindi per favore, puoi provare ad aggiungere:

resolver 127.0.0.11

nel file di configurazione di nginx?


Aggiungi più resolver comeresolver 127.0.0.11 8.8.8.8;
— Leonardo Chaia

1
No, poiché interrogherà in round robin come indicato nei documenti: i server dei nomi vengono interrogati in modo round robin.
— dalore

6

Se sei così perso per leggere l'ultimo commento. Ho raggiunto un'altra soluzione.

Il problema principale è il modo in cui hai chiamato i nomi dei servizi.

In questo caso, se nel tuo docker-compose.yml, i servizi per php sono chiamati "api" o qualcosa del genere, devi assicurarti che nel file nginx.confla riga che inizia con fastcgi_passabbia lo stesso nome del servizio php. cioèfastcgi_pass api:9000;


3

Ho avuto lo stesso problema perché c'erano due reti definite nel mio docker-compose.yml: una backend e una frontend.
Quando l'ho modificato per eseguire i contenitori sulla stessa rete predefinita, tutto ha iniziato a funzionare correttamente.


Questa è ben lontana dall'essere una risposta.
— dargmuesli

2

Ho avuto lo stesso problema e l'ho risolto. Aggiungi la seguente riga alla sezione docker-compose.yml nginx:

links:
  - php:waapi_php_1

L'host nella sezione fastcgi_pass di configurazione nginx dovrebbe essere collegato all'interno della configurazione docker-compose.yml nginx.


1

Due cose che vale la pena menzionare:

  • Utilizzando lo stesso bridge di rete
  • Utilizzo linksper aggiungere host resol

Il mio esempio:

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

Se non specifichi un bridge di rete speciale, tutti useranno lo stesso predefinito.


1

A prima vista, mi sono perso il fatto che il mio servizio "web" non fosse effettivamente avviato, quindi è per questo che nginx non è riuscito a trovare alcun host

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 sto avendo lo stesso problema. La mia applicazione non è in esecuzione, quindi ricevo lo stesso errore. ho messo uwsgi-file come run.py in app.ini che avrebbe dovuto eseguire l'app ma non sta accadendo
— isrj5

0

Con i collegamenti viene applicato un ordine di avvio del contenitore. Senza collegamenti i contenitori possono iniziare in qualsiasi ordine (o davvero tutti in una volta).

Penso che la vecchia configurazione avrebbe potuto riscontrare lo stesso problema, se il waapi_php_1contenitore fosse lento all'avvio.

Penso che per farlo funzionare, potresti creare uno script entrypoint nginx che esegue il polling e attende che il contenitore php sia avviato e pronto.

Non sono sicuro che nginx abbia un modo per ritentare automaticamente la connessione all'upstream, ma se lo fa, sarebbe un'opzione migliore.


E come si eseguono i sondaggi?
— Attila Szeremi


0

Forse la scelta migliore per evitare problemi di collegamento dei contenitori è il collegamento in rete funzionalità di

Ma per far funzionare questo, docker crea voci in / etc / hosts per ogni contenitore dai nomi assegnati a ciascun contenitore.

con docker-compose --x-networking -up è qualcosa come [docker_compose_folder] - [service] - [incremental_number]

Per non dipendere da modifiche impreviste in questi nomi è necessario utilizzare il parametro

nome_contenitore

nel tuo docker-compose.yml come segue:

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

Assicurati che sia lo stesso nome assegnato nel tuo file di configurazione per questo servizio. Sono abbastanza sicuro che ci siano modi migliori per farlo, ma è un buon approccio per iniziare.


0

La mia soluzione alternativa (dopo molte prove ed errori):

  • Per aggirare questo problema, ho dovuto ottenere il nome completo del container Docker 'upstream', trovato eseguendo docker network inspect my-special-docker-networke ottenendo la nameproprietà completa del container upstream in quanto tale:

    "Containers": {
         "39ad8199184f34585b556d7480dd47de965bc7b38ac03fc0746992f39afac338": {
              "Name": "my_upstream_container_name_1_2478f2b3aca0",
    
  • Quindi ha usato questo nel my-network.local.conffile NGINX nel locationblocco della proxy_passproprietà: (Nota l'aggiunta del GUID al nome del contenitore):

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

A differenza del precedente funzionante, ma ora rotto:

    location / {
        proxy_pass http://my_upstream_container_name_1:3000

La causa più probabile è una recente modifica a Docker Compose, nel loro schema di denominazione predefinito per i contenitori, come elencato qui .

Questo sembra accadere per me e il mio team al lavoro, con le ultime versioni nginxdell'immagine Docker :

  • Ho aperto problemi con loro nella finestra mobile / componi GitHub qui

0

(nuovo di nginx) Nel mio caso il nome della cartella era sbagliato

Per config

upstream serv {
    server ex2_app_1:3000;
}

assicurati che la cartella dell'app sia nella cartella ex2:

ex2 / app / ...


0

questo errore mi è apparso perché la mia php-fpmimmagine è abilitata crone non ho idea del perché


0

Il mio problema era che mi ero dimenticato di specificare l'alias di rete in docker-compose.yml in php-fpm

    networks:
      - u-online

Funziona bene!

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

-1

Aggiungi la sezione dei collegamenti alla configurazione del tuo contenitore nginx.

Devi rendere visibile il phpcontenitore al nginxcontenitore.

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
Conosco i collegamenti, tuttavia Docker li ha contrassegnati come deprecati nella versione 1.9 che è uscita una settimana fa a favore dell'utilizzo della rete di Docker. Vorrei una soluzione che lo utilizzi, in parte perché i collegamenti hanno un problema con il collegamento circolare che il networking non dovrebbe avere.
— Attila Szeremi

1
In CHANGELOG.md non vedo linkessere deprecato. Mi sto perdendo qualcosa?
— nessuno

Non l'ho visto neanche lì dentro; tuttavia quando docker-compose --x-networking updocker-compose.ymlWARNING: "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.
— eseguo

Ok, ho trovato dove si trova la deprecazione. L'unica idea che ho è: il tuo docker-compose.ymlfile si trova in una cartella denominata waapi?
— nessuno

Sì, è in una cartella denominatawaapi
— Attila Szeremi
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.