Red de Docker - nginx: [emerg] host no encontrado en upstream

99

Recientemente comencé a migrar a las funciones de red de Docker 1.9 y Docker-Compose 1.5 para reemplazar el uso de enlaces.

Hasta ahora, con los enlaces, no hubo problemas con nginx para conectarse a mi servidor php5-fpm fastcgi ubicado en un servidor diferente en un grupo a través de docker-compose. Sin embargo, recientemente cuando ejecuto docker-compose --x-networking upmis contenedores php-fpm, mongo y nginx arrancan, sin embargo, nginx se cierra de inmediato[emerg] 1#1: host not found in upstream "waapi_php_1" in /etc/nginx/conf.d/default.conf:16

Sin embargo, si ejecuto el comando docker-compose nuevamente mientras se ejecutan los contenedores php y mongo (nginx salió), nginx se inicia y funciona bien a partir de ese momento.

Este es mi docker-compose.ymlarchivo:

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

Este es mi default.confpara 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;
    }
}

¿Cómo puedo hacer que nginx funcione con una sola llamada docker-compose?

Attila Szeremi
fuente
3
Yo también me estoy encontrando con esto. No estoy seguro de si se trata de un error con el archivo de redacción o un error con la propia red de Docker.
jrdn

Respuestas:

26

Existe la posibilidad de usar "volume_from" como una solución alternativa hasta que se introduzca la función depende_en (que se explica a continuación). Todo lo que tiene que hacer es cambiar su archivo de composición de docker como se muestra a continuación:

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

Una gran advertencia en el enfoque anterior es que los volúmenes de php están expuestos a nginx, lo cual no es deseado. Pero por el momento, esta es una solución alternativa específica de Docker que podría usarse.

Depende de la función Esto probablemente sería una respuesta futurista. Porque la funcionalidad aún no está implementada en Docker (a partir de 1.9)

Existe una propuesta para introducir "depende_en" en la nueva función de red introducida por Docker. Pero existe un debate de larga duración sobre el mismo @ https://github.com/docker/compose/issues/374 Por lo tanto, una vez que se implemente, la función depend_on podría usarse para ordenar el inicio del contenedor, pero en el momento, tendría que recurrir a uno de los siguientes:

  1. hacer que nginx vuelva a intentarlo hasta que el servidor php esté activo; preferiría este
  2. use volums_from como solución alternativa como se describe anteriormente; evitaría usar esto debido a la fuga de volumen en contenedores innecesarios.
Phani
fuente
3
Esto no me solucionó.
Gijs
@Gijs, si puedes publicar cuál es tu caso exacto y qué no funcionó, alguien podría ayudar en el foro.
Phani
4
volume_from están en desuso
Roma Rush
Me encontré con un problema en Azure App Service Docker Compose (versión preliminar) con esto. También tuve que asegurarme de que todos los links:que incluí en nginx usaran el mismo nombre que el servicio en sí, como - my-service:my-serviceen este ejemplo - mongo:mongo.
Greg
29

Esto se puede solucionar con la depends_ondirectiva mencionada ya que está implementada ahora (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

Probado con éxito con:

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

Encuentre más detalles en la documentación .

También hay un artículo muy interesante dedicado a este tema: Control del orden de inicio en Compose

Czerasz
fuente
12

Puede configurar las directivas max_fails y fail_timeout de nginx para indicar que el nginx debe reintentar el número x de solicitudes de conexión al contenedor antes de fallar en la indisponibilidad del servidor ascendente.

Puede ajustar estos dos números según su infraestructura y la velocidad a la que se desarrolla toda la configuración. Puede leer más detalles sobre la sección de controles de estado de la siguiente URL: http://nginx.org/en/docs/http/load_balancing.html

A continuación se muestra el extracto de http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server max_fails=number

establece el número de intentos fallidos de comunicarse con el servidor que deberían ocurrir en la duración establecida por el parámetro fail_timeout para considerar que el servidor no está disponible durante un período también establecido por el parámetro fail_timeout. De forma predeterminada, el número de intentos fallidos se establece en 1. El valor cero desactiva la contabilización de intentos. Lo que se considera un intento fallido está definido por las directivas proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream y memcached_next_upstream.

fail_timeout=time

establece el tiempo durante el cual debe ocurrir el número especificado de intentos fallidos de comunicarse con el servidor para considerar que el servidor no está disponible; y el período de tiempo que el servidor se considerará no disponible. De forma predeterminada, el parámetro está configurado en 10 segundos.

Para ser precisos, su archivo de configuración nginx modificado debe ser el siguiente (esta secuencia de comandos asume que todos los contenedores están activos por lo menos 25 segundos, si no, cambie el fail_timeout o max_fails en la sección anterior): Nota: no lo hice probar el guión yo mismo, para que pueda probarlo.

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

Además, según la siguiente nota de docker ( https://github.com/docker/docker.github.io/blob/master/compose/networking.md#update-containers ), es evidente que la lógica de reintento para verificar la salud de los otros contenedores no es responsabilidad del estibador y, más bien, los contenedores deben hacer el control de salud ellos mismos.

Actualizar contenedores

Si realiza un cambio de configuración en un servicio y ejecuta docker-compose up para actualizarlo, el contenedor antiguo se eliminará y el nuevo se unirá a la red con una dirección IP diferente pero con el mismo nombre. Los contenedores en ejecución podrán buscar ese nombre y conectarse a la nueva dirección, pero la dirección anterior dejará de funcionar.

Si alguno de los contenedores tiene conexiones abiertas al contenedor anterior, se cerrará. Es responsabilidad del contenedor detectar esta condición, buscar el nombre nuevamente y volver a conectarse.

Phani
fuente
3
Esto no funcionará. lea la advertencia al final de esta sección en los documentos de nginx: "Si solo hay un servidor en un grupo, los parámetros max_fails, fail_timeout y slow_start se ignoran, y dicho servidor nunca se considerará no disponible".
Ferguzz
1
@Ferguzz eso fue una buena captura. Como solución alternativa, puede agregar dos entradas de alias del mismo contenedor para hacer un grupo del mismo contenedor.
Phani
Como solución alternativa, he proporcionado en la misma pregunta el uso de "volúmenes_de" para vincular los contenedores y hacerlos esperar hasta que se carguen otros contenedores. Esto es trabajo para mí.
Phani
7

Creo que Nginx no tiene en cuenta el solucionador de Docker (127.0.0.11), así que, por favor, ¿puedes intentar agregar:

resolver 127.0.0.11

en su archivo de configuración de nginx?

Thomas Decaux
fuente
Agregue múltiples resolutores comoresolver 127.0.0.11 8.8.8.8;
Leonardo Chaia
1
No, ya que consultará en round robin como se indica en los documentos: los servidores de nombres se consultan en round robin.
dalore
6

Si estás tan perdido, lee el último comentario. He llegado a otra solución.

El principal problema es la forma en que nombró los nombres de los servicios.

En este caso, si en tu docker-compose.yml, los servicios para php se llaman "api" o algo así, debes asegurarte de que en el archivo nginx.confla línea que comienza con fastcgi_passtenga el mismo nombre que el servicio php. es decirfastcgi_pass api:9000;

Julian
fuente
3

Tuve el mismo problema porque había dos redes definidas en mi docker-compose.yml: una backend y una frontend.
Cuando cambié eso para ejecutar contenedores en la misma red predeterminada, todo comenzó a funcionar bien.

smola
fuente
Esto está lejos de ser una respuesta.
dargmuesli
2

Tuve el mismo problema y lo solucioné. Agregue la siguiente línea a la sección nginx docker-compose.yml:

links:
  - php:waapi_php_1

El host en la sección nginx config fastcgi_pass debe estar vinculado dentro de la configuración nginx de docker-compose.yml.

st0at
fuente
1

Dos cosas que vale la pena mencionar:

  • Usando el mismo puente de red
  • Usando linkspara agregar hosts resol

Mi ejemplo:

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

Si no especifica un puente de red especial, todos usarán el mismo predeterminado.

NOZUONOHIGH
fuente
1

A primera vista, me perdí que mi servicio "web" en realidad no se inició, por eso nginx no pudo encontrar ningún 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
Alveona
fuente
Hey, estoy teniendo el mismo problema. Mi aplicación no se está ejecutando, por lo que recibo el mismo error. He puesto uwsgi-file como run.py en app.ini que debería haber ejecutado la aplicación pero no está sucediendo
isrj5
0

Con los enlaces, se aplica un orden de inicio del contenedor. Sin enlaces, los contenedores pueden comenzar en cualquier orden (o realmente todos a la vez).

Creo que la configuración anterior podría haber tenido el mismo problema, si el waapi_php_1contenedor tardaba en iniciarse.

Creo que para que funcione, podría crear un script de punto de entrada nginx que sondea y espera a que el contenedor php se inicie y esté listo.

No estoy seguro de si nginx tiene alguna forma de reintentar la conexión al flujo ascendente automáticamente, pero si lo hace, sería una mejor opción.

dnefina
fuente
¿Y cómo hago las encuestas?
Attila Szeremi
0

Quizás la mejor opción para evitar problemas de vinculación de contenedores son las funciones de red de la ventana acoplable

Pero para que esto funcione, Docker crea entradas en / etc / hosts para cada contenedor a partir de los nombres asignados a cada contenedor.

con docker-compose --x-networking -up es algo así como [docker_compose_folder] - [servicio] - [incremental_number]

Para no depender de cambios inesperados en estos nombres, debe usar el parámetro

nombre_contenedor

en su docker-compose.yml de la siguiente manera:

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

Asegúrese de que sea el mismo nombre asignado en su archivo de configuración para este servicio. Estoy bastante seguro de que hay mejores formas de hacer esto, pero es un buen enfoque para empezar.

JorelC
fuente
0

Mi solución (después de mucho ensayo y error):

  • Para solucionar este problema, tuve que obtener el nombre completo del contenedor Docker 'ascendente', que se encuentra al ejecutar docker network inspect my-special-docker-networky obtener la namepropiedad completa del contenedor ascendente como tal:

    "Containers": {
         "39ad8199184f34585b556d7480dd47de965bc7b38ac03fc0746992f39afac338": {
              "Name": "my_upstream_container_name_1_2478f2b3aca0",
    
  • Luego usé esto en el my-network.local.confarchivo NGINX en el locationbloque de la proxy_passpropiedad: (Tenga en cuenta la adición del GUID al nombre del contenedor):

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

A diferencia de lo que antes funcionaba, pero ahora está roto:

    location / {
        proxy_pass http://my_upstream_container_name_1:3000

La causa más probable es un cambio reciente en Docker Compose, en su esquema de nomenclatura predeterminado para contenedores, como se enumera aquí .

Esto parece estar sucediendo para mí y mi equipo en el trabajo, con las últimas versiones de la nginximagen de Docker :

  • Abrí problemas con ellos en la ventana acoplable / componer GitHub aquí
arcadia_168
fuente
0

(nuevo en nginx) En mi caso, era un nombre de carpeta incorrecto

Para config

upstream serv {
    server ex2_app_1:3000;
}

asegúrese de que la carpeta de la aplicación esté en la carpeta ex2:

ex2 / app / ...

vijeth.ag
fuente
0

Este error me apareció porque mi php-fpmimagen estaba habilitada crony no tengo idea de por qué

Ruan Nawe
fuente
0

Mi problema fue que olvidé especificar el alias de red en docker-compose.yml en php-fpm

    networks:
      - u-online

¡Funciona bien!

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
Юрий Светлов
fuente
-1

Agregue la sección de enlaces a la configuración de su contenedor nginx.

Tienes que hacer visible el phpcontenedor al nginxcontenedor.

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
fuente
1
Conozco los enlaces, sin embargo, Docker los marcó en desuso en la versión 1.9 que salió hace una semana a favor del uso de la red de Docker. Me gustaría una solución que utilice eso, en parte porque los enlaces tienen un problema con los enlaces circulares que las redes no deberían tener.
Attila Szeremi
1
En CHANGELOG.md , no veo que linkesté obsoleto. ¿Me estoy perdiendo de algo?
nessuno
Tampoco vi eso allí; sin embargo, cuando corro docker-compose --x-networking upcon enlaces definidos en mi docker-compose.yml, recibo esta advertencia clara: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, encontré dónde está la desaprobación. La única idea que tengo es: ¿está docker-compose.ymlarchivado en una carpeta con nombre waapi?
nessuno
Sí, está en una carpeta llamadawaapi
Attila Szeremi