web-dev-qa-db-fra.com

Docker Networking - nginx: [émergent] Hôte introuvable en amont

J'ai récemment commencé à migrer vers Docker 1.9 et les fonctionnalités réseau de Docker-Compose 1.5 pour remplacer les liens.

Jusqu'à présent, avec des liens, il n'y avait aucun problème avec la connexion de nginx à mon serveur fastcgi php5-fpm situé sur un serveur différent dans un groupe via docker-compose. Récemment, lorsque j’exécute docker-compose --x-networking up, mes conteneurs php-fpm, mongo et nginx s’amorcent, mais nginx se ferme immédiatement avec [emerg] 1#1: Host not found in upstream "waapi_php_1" in /etc/nginx/conf.d/default.conf:16.

Cependant, si j'exécute à nouveau la commande docker-compose pendant que les conteneurs php et mongo sont en cours d'exécution (nginx a quitté), nginx démarre et fonctionne correctement à partir de ce moment.

Ceci est mon fichier docker-compose.yml:

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

Ceci est mon default.conf pour 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;
    }
}

Comment faire en sorte que nginx fonctionne avec un seul appel composé par un menu fixe?

59
Attila Szeremi

Il est possible d'utiliser "volumes_from" comme solution de contournement jusqu'à l'introduction de la fonction de dépendance (expliquée ci-dessous). Tout ce que vous avez à faire est de changer votre fichier docker-compose comme ci-dessous:

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

Une grande mise en garde dans l'approche ci-dessus est que les volumes de php sont exposés à nginx, ce qui n'est pas souhaité. Mais pour le moment, cette solution de contournement spécifique au docker pourrait être utilisée. 

includes_on feature Ce serait probablement une réponse futuriste. Parce que la fonctionnalité n'est pas encore implémentée dans Docker (à partir de la version 1.9)

Il est proposé d'introduire "depend_on" dans la nouvelle fonctionnalité de mise en réseau introduite par Docker. Mais il y a un long débat autour du même @ (https://github.com/docker/compose/issues/374 Par conséquent, une fois implémentée, la fonction depend_on pourrait être utilisée pour commander le début du conteneur. -up, mais pour le moment, vous devrez recourir à l'un des éléments suivants:

  1. faire réessayer nginx jusqu'à ce que le serveur php soit en place - je préférerais celui-ci
  2. utilisez la solution de contournement de volums_from comme décrit ci-dessus - je l’éviterais, en raison des fuites de volume dans des conteneurs inutiles. 
18
Phani

Ceci peut être résolu avec la directive depends_on mentionnée depuis sa mise en œuvre maintenant (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

Testé avec succès avec:

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

Trouvez plus de détails dans la documentation .

Un article très intéressant est également consacré à ce sujet: Contrôle de l’ordre de démarrage dans Compose

13
czerasz

Vous pouvez définir les directives max_fails et fail_timeout de nginx pour indiquer que nginx doit réessayer le nombre x de demandes de connexion au conteneur avant l'échec de l'indisponibilité du serveur en amont. 

Vous pouvez régler ces deux chiffres en fonction de votre infrastructure et de la vitesse à laquelle toute la configuration est imminente. Vous pouvez lire plus de détails sur la section des contrôles de santé de l'URL ci-dessous: http://nginx.org/en/docs/http/load_balancing.html

Voici l'extrait de http://nginx.org/en/docs/http/ngx_http_upstream_module.html#servermax_fails=number

définit le nombre de tentatives infructueuses de communication avec le serveur qui doit se produire pendant la durée définie par fail_timeout paramètre à considérer le serveur indisponible pour une durée également défini par le paramètre fail_timeout. Par défaut, le nombre d'échecs tentatives est défini sur 1. La valeur zéro désactive la comptabilisation de tentatives. Ce qui est considéré comme une tentative infructueuse est défini par le proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream et les directives memcached_next_upstream.

fail_timeout=time

définit le temps pendant lequel le nombre spécifié d'échecs les tentatives de communication avec le serveur doivent arriver à considérer le serveur indisponible; et la période pendant laquelle le serveur sera considéré comme indisponible. Par défaut, le paramètre est défini sur 10 secondes.

Pour être précis, votre fichier de configuration nginx modifié devrait être le suivant (ce script suppose que tous les conteneurs sont actifs au moins 25 secondes. Sinon, veuillez modifier le paramètre fail_timeout ou max_fails dans la section en amont ci-dessous): Remarque: I Je n'ai pas testé le script moi-même, vous pouvez donc l'essayer!

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

En outre, comme indiqué dans la note suivante de docker ( - https://github.com/docker/compose/blob/master/docs/networking.md ), il est évident que la logique de nouvelle tentative permettant de vérifier l'intégrité du les autres conteneurs ne sont pas de la responsabilité du docker et ces derniers doivent effectuer le bilan de santé eux-mêmes 

Mise à jour des conteneurs

Si vous modifiez la configuration d'un service et exécutez docker-compose pour le mettre à jour, l'ancien conteneur sera supprimé et le nouveau rejoindra le réseau sous une adresse IP différente mais sous le même nom . Les conteneurs en cours pourront rechercher ce nom et se connecter à la nouvelle adresse, mais l'ancienne adresse cessera de fonctionner.

Si des conteneurs ont des connexions ouvertes sur l'ancien conteneur, ils sera fermé. C'est la responsabilité du conteneur de détecter ceci condition, recherchez à nouveau le nom et reconnectez-vous.

8
Phani

Je crois que Nginx ne prend pas en compte le résolveur de Docker (127.0.0.11), alors veuillez essayer d’ajouter:

resolver 127.0.0.11

dans votre fichier de configuration nginx?

4
Thomas Decaux

Si vous êtes si perdu pour lire le dernier commentaire. J'ai atteint une autre solution.

Le problème principal est la façon dont vous avez nommé les noms de services.

Dans ce cas, si dans votre docker-compose.yml, le service pour php s'appelle "api" ou quelque chose du genre, vous devez vous assurer que dans le fichier nginx.conf la ligne commençant par fastcgi_pass porte le même nom que le service php. i.e fastcgi_pass api:9000;

2
julian

avoir le même problème jusqu'à ce qu'il y avait dans un docker-compose.yml deux réseaux définis: backend et frontend. Lorsque tous les conteneurs sont exécutés sur le même réseau par défaut, tout fonctionne correctement. 

1
smola

Avait le même problème et résolu. Veuillez ajouter la ligne suivante à la section nginx de docker-compose.yml:

links:
  - php:waapi_php_1

L'hôte dans la section fastcgi_pass de nginx config doit être lié à la configuration de docker-compose.yml nginx.

1
st0at

Ma solution de contournement (après de nombreux essais et erreurs):

  • Afin de résoudre ce problème, je devais obtenir le nom complet du conteneur Docker 'en amont', trouvé en exécutant docker network inspect my-special-docker-network et en obtenant la propriété complète name du conteneur en amont en tant que telle:

    "Containers": {
         "39ad8199184f34585b556d7480dd47de965bc7b38ac03fc0746992f39afac338": {
              "Name": "my_upstream_container_name_1_2478f2b3aca0",
    
  • Ensuite, cela utilisé dans le fichier NGINX my-network.local.conf du bloc location de la propriété proxy_pass: (Notez l'ajout du GUID au nom du conteneur):

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

Contrairement à l'ancien, mais maintenant cassé:

    location / {
        proxy_pass http://my_upstream_container_name_1:3000

La cause la plus probable est une modification récente de Docker Compose, dans leur schéma de nommage par défaut pour les conteneurs, comme indiqué dans la liste ici .

Cela semble se produire pour moi et mon équipe au travail, avec les dernières versions de l'image Docker nginx:

  • J'ai ouvert des problèmes avec eux sur le docker/compose GitHub ici
0
arcadia_168

(nouveau sur nginx) Dans mon cas, le nom de dossier était incorrect

Pour config

upstream serv {
    server ex2_app_1:3000;
}

assurez-vous que le dossier de l'application est dans le dossier ex2:

ex2/app/...

0
vijeth.ag

Avec les liens, un ordre de démarrage du conteneur est appliqué. Sans liens, les conteneurs peuvent commencer dans n'importe quel ordre (ou vraiment tous en même temps).

Je pense que l'ancienne configuration aurait pu rencontrer le même problème si le conteneur waapi_php_1 était lent à démarrer.

Je pense que pour que cela fonctionne, vous pouvez créer un script nginx entrypoint qui interroge et attend que le conteneur php soit démarré et prêt.

Je ne suis pas sûr que nginx puisse réessayer automatiquement la connexion en amont, mais si c'est le cas, ce serait une meilleure option.

0
dnephin

Peut-être que le meilleur choix pour éviter les problèmes de liaison de conteneurs est le fonctionnalités de docker

Mais pour que cela fonctionne, docker crée des entrées dans le répertoire/etc/hosts pour chaque conteneur à partir des noms attribués à chaque conteneur. 

avec docker-compose --x-networking-up ressemble à peu près à [docker_compose_folder] - [service] - [numéro incrémental]

Pour ne pas dépendre de changements inattendus dans ces noms, vous devez utiliser le paramètre

nom_conteneur

dans votre docker-compose.yml comme suit:

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

Assurez-vous qu'il s'agit du même nom que celui attribué dans votre fichier de configuration pour ce service. Je suis à peu près sûr qu'il existe de meilleures façons de le faire, mais c'est une bonne approche pour commencer.

0
JorelC

Deux choses à noter:

  • Utiliser le même pont réseau
  • Utiliser links pour ajouter la résolution des hôtes

Mon exemple:

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 vous ne spécifiez pas de pont réseau spécial, ils utiliseront tous le même pont par défaut.

0
NOZUONOHIGH

Vous devez utiliser quelque chose comme docker-gen pour mettre à jour dynamiquement la configuration de nginx lorsque votre backend est en place. 

Voir:

Je pense que Nginx + (version premium) contient également un paramètre de résolution ( http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream )

0
Laurent B