Rede Docker - nginx: host [emerg] não encontrado no upstream


92

Recentemente, comecei a migrar para os recursos de rede do Docker 1.9 e Docker-Compose 1.5 para substituir o uso de links.

Até agora, com os links, não houve problemas com a conexão do nginx ao meu servidor fastcgi php5-fpm localizado em um servidor diferente em um grupo via docker-compose. Recentemente, porém, quando eu executo docker-compose --x-networking upmeus contêineres php-fpm, mongo e nginx inicializam, no entanto, o nginx fecha imediatamente com[emerg] 1#1: host not found in upstream "waapi_php_1" in /etc/nginx/conf.d/default.conf:16

No entanto, se eu executar o comando docker-compose novamente enquanto os contêineres php e mongo estiverem em execução (nginx foi encerrado), o nginx será iniciado e funcionará bem a partir de então.

Este é o meu docker-compose.ymlarquivo:

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 é o meu 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;
    }
}

Como posso fazer o nginx funcionar com apenas uma única chamada docker-compose?


3
Eu também estou encontrando isso. Não tenho certeza se é um erro com o arquivo de composição ou um bug com a própria rede do docker.
jrdn

Respostas:


24

Existe a possibilidade de usar "volumes_from" como uma solução alternativa até que o recurso depends_on (discutido abaixo) seja introduzido. Tudo que você precisa fazer é alterar o arquivo docker-compose conforme abaixo:

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

Uma grande advertência na abordagem acima é que os volumes de php são expostos ao nginx, o que não é desejado. Mas, no momento, esta é uma solução alternativa específica do docker que pode ser usada.

recurso Depende_on Esta provavelmente seria uma resposta futurística. Porque a funcionalidade ainda não foi implementada no Docker (a partir de 1.9)

Há uma proposta para introduzir "depends_on" no novo recurso de rede introduzido pelo Docker. Mas há um longo debate sobre o mesmo @ https://github.com/docker/compose/issues/374 Portanto, uma vez implementado, o recurso depends_on poderia ser usado para solicitar a inicialização do contêiner, mas no momento, você teria que recorrer a um dos seguintes:

  1. faça o nginx tentar novamente até que o servidor php esteja ativo - eu preferiria este
  2. use volums_from workaround conforme descrito acima - eu evitaria usar isso, por causa do vazamento de volume em recipientes desnecessários.

3
Isso não resolveu para mim.
Gijs

@Gijs se você puder postar qual é o seu caso exato e o que não funcionou, alguém poderia ajudar no fórum.
Phani de

4
volumes_from estão obsoletos
Roma Rush

Eu tive um problema no Azure App Service Docker Compose (visualização) com isso. Também tive que me certificar de que qualquer um links:incluído no nginx usava o mesmo nome do serviço em si, como - my-service:my-serviceneste exemplo - mongo:mongo.
Greg

27

Isso pode ser resolvido com a depends_ondiretiva mencionada, uma vez que está implementada agora (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

Testado com sucesso com:

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

Encontre mais detalhes na documentação .

Há também um artigo muito interessante dedicado a este tópico: Controlando a ordem de inicialização no Compose


12

Você pode definir as diretivas max_fails e fail_timeout do nginx para indicar que o nginx deve repetir o número x de solicitações de conexão para o contêiner antes de falhar na indisponibilidade do servidor upstream.

Você pode ajustar esses dois números de acordo com sua infraestrutura e velocidade em que toda a configuração está surgindo. Você pode ler mais detalhes sobre a seção de verificações de saúde do URL abaixo: http://nginx.org/en/docs/http/load_balancing.html

A seguir está o trecho de http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server max_fails=number

define o número de tentativas malsucedidas de comunicação com o servidor que devem acontecer na duração definida pelo parâmetro fail_timeout para considerar o servidor indisponível por um período também definido pelo parâmetro fail_timeout. Por padrão, o número de tentativas malsucedidas é definido como 1. O valor zero desativa a contabilização de tentativas. O que é considerado uma tentativa malsucedida é definido pelas diretivas proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream e memcached_next_upstream.

fail_timeout=time

define o tempo durante o qual o número especificado de tentativas malsucedidas de comunicação com o servidor deve ocorrer para considerar o servidor indisponível; e o período de tempo em que o servidor será considerado indisponível. Por padrão, o parâmetro é definido como 10 segundos.

Para ser mais preciso, o arquivo de configuração nginx modificado deve ser o seguinte (este script pressupõe que todos os contêineres estão ativos em pelo menos 25 segundos, caso contrário, altere fail_timeout ou max_fails na seção upstream abaixo): Observação: não teste o script sozinho, para que você possa tentar!

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

Além disso, de acordo com a seguinte Nota do docker ( https://github.com/docker/docker.github.io/blob/master/compose/networking.md#update-containers ), é evidente que a lógica de repetição para verificação a saúde dos outros contêineres não é de responsabilidade do estivador e, em vez disso, os contêineres devem fazer a verificação de saúde por conta própria.

Atualizando contêineres

Se você alterar a configuração de um serviço e executar docker-compose up para atualizá-lo, o contêiner antigo será removido e o novo ingressará na rede com um endereço IP diferente, mas com o mesmo nome. Os contêineres em execução poderão pesquisar esse nome e se conectar ao novo endereço, mas o endereço antigo deixará de funcionar.

Se algum contêiner tiver conexões abertas com o contêiner antigo, eles serão fechados. É responsabilidade do contêiner detectar essa condição, pesquisar o nome novamente e reconectar.


3
Isso não vai funcionar. leia a advertência no final desta seção nos documentos nginx: "Se houver apenas um único servidor em um grupo, os parâmetros max_fails, fail_timeout e slow_start são ignorados e tal servidor nunca será considerado indisponível."
Ferguzz

1
@Ferguzz foi uma boa pegada. Como solução alternativa, você pode adicionar duas entradas de alias do mesmo contêiner para criar um grupo do mesmo contêiner.
Phani

Como solução alternativa, forneci na mesma pergunta o uso de "volumes_from" para vincular os contêineres e fazê-los esperar até que outros contêineres sejam carregados. Isso está funcionando para mim.
Phani

7

Acredito que o Nginx não leva em conta o resolvedor do Docker (127.0.0.11), então, por favor, você pode tentar adicionar:

resolver 127.0.0.11

em seu arquivo de configuração nginx?


Adicionar vários resolvedores comoresolver 127.0.0.11 8.8.8.8;
Leonardo Chaia

Não, pois ele consultará em round robin conforme declarado nos documentos: Os servidores de nomes são consultados em round robin.
dalore,

6

Se você está tão perdido para ler o último comentário. Cheguei a outra solução.

O principal problema é a maneira como você nomeou os nomes dos serviços.

Neste caso, se no seu docker-compose.yml, os serviços para php são chamados de "api" ou algo parecido, você deve garantir que no arquivo nginx.confa linha que começa com fastcgi_passtenha o mesmo nome do serviço php. iefastcgi_pass api:9000;


2

Teve o mesmo problema e resolveu. Adicione a seguinte linha à seção docker-compose.yml nginx:

links:
  - php:waapi_php_1

O host na seção fastcgi_pass da configuração do nginx deve ser vinculado à configuração docker-compose.yml nginx.


2

Eu tive o mesmo problema porque havia duas redes definidas no meu docker-compose.yml: um backend e um frontend.
Quando mudei isso para executar contêineres na mesma rede padrão, tudo começou a funcionar bem.


Isso está longe de ser uma resposta.
dargmuesli

1

Duas coisas que vale a pena mencionar:

  • Usando a mesma ponte de rede
  • Usando linkspara adicionar hosts resol

Meu exemplo:

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 você não especificar uma ponte de rede especial, todas elas usarão a mesma ponte padrão.


1

À primeira vista, não percebi que meu serviço "web" não foi realmente iniciado, então é por isso que o nginx não conseguiu encontrar nenhum 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

ei, estou tendo o mesmo problema. Meu aplicativo não está funcionando, então estou recebendo o mesmo erro. coloquei o arquivo uwsgi como run.py no app.ini, que deveria ter executado o aplicativo, mas não está acontecendo
isrj5

0

Com os links, há uma ordem de inicialização do contêiner sendo aplicada. Sem links, os containers podem começar em qualquer ordem (ou realmente todos de uma vez).

Acho que a configuração antiga poderia ter encontrado o mesmo problema, se o waapi_php_1contêiner demorasse para iniciar.

Eu acho que para fazê-lo funcionar, você poderia criar um script de ponto de entrada nginx que monitora e aguarda o contêiner php ser iniciado e pronto.

Não tenho certeza se o nginx tem alguma maneira de tentar novamente a conexão com o upstream automaticamente, mas se tiver, seria uma opção melhor.


E como faço a votação?
Attila Szeremi


0

Talvez a melhor escolha para evitar problemas de vinculação de contêineres sejam os recursos de rede do docker

Mas para fazer isso funcionar, o docker cria entradas em / etc / hosts para cada container a partir de nomes atribuídos a cada container.

com docker-compose --x-networking -up é algo como [docker_compose_folder] - [serviço] - [incremental_number]

Para não depender de mudanças inesperadas nesses nomes, você deve usar o parâmetro

container_name

em docker-compose.yml da seguinte maneira:

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

Certifique-se de que é o mesmo nome atribuído em seu arquivo de configuração para este serviço. Tenho certeza de que existem maneiras melhores de fazer isso, mas é uma boa abordagem para começar.


0

Minha solução alternativa (depois de muitas tentativas e erros):

  • Para contornar esse problema, tive que obter o nome completo do contêiner Docker 'upstream', encontrado executando docker network inspect my-special-docker-networke obtendo a namepropriedade completa do contêiner upstream, como:

    "Containers": {
         "39ad8199184f34585b556d7480dd47de965bc7b38ac03fc0746992f39afac338": {
              "Name": "my_upstream_container_name_1_2478f2b3aca0",
    
  • Em seguida, usei isso no my-network.local.confarquivo NGINX no locationbloco da proxy_passpropriedade: (Observe a adição do GUID ao nome do container):

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

Ao contrário do trabalho anterior, mas agora quebrado:

    location / {
        proxy_pass http://my_upstream_container_name_1:3000

A causa mais provável é uma mudança recente no Docker Compose, em seu esquema de nomenclatura padrão para contêineres, conforme listado aqui .

Isso parece estar acontecendo comigo e com minha equipe de trabalho, com as versões mais recentes da nginximagem Docker :

  • Abri problemas com eles no docker / redigir GitHub aqui

0

(novo no nginx) No meu caso, era o nome da pasta errado

Para configuração

upstream serv {
    server ex2_app_1:3000;
}

certifique-se de que a pasta do aplicativo esteja na pasta ex2:

ex2 / app / ...


0

este erro apareceu para mim porque minha php-fpmimagem habilitou cron, e eu não tenho ideia do porquê


-1

Adicione os links seção de à configuração do contêiner nginx.

Você deve tornar o phpcontêiner visível para o nginxcontêiner.

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
Eu sei sobre os links, no entanto, o Docker os marcou como obsoletos na versão 1.9 que saiu há uma semana em favor do uso da rede do Docker. Eu gostaria de uma solução que use isso, em parte porque os links têm um problema com links circulares que a rede não deveria ter.
Attila Szeremi

1
Em CHANGELOG.md , não vejo linkseu uso suspenso. Estou esquecendo de algo?
nessuno

Eu não vi isso ali também; no entanto, quando executo docker-compose --x-networking upcom links definidos no meu docker-compose.yml, recebo este aviso claro: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, descobri onde está a suspensão de uso. A única ideia que tenho é: seu docker-compose.ymlarquivo está em uma pasta chamada waapi?
nessuno

Sim, está em uma pasta chamadawaapi
Attila Szeremi
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.