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.