Como Corrigir o Erro "Host Not Found In Upstream" do Nginx em Docker?

Publicado 13 de outubro de 2024

Problema: Erro "Host Not Found In Upstream" do Nginx

O erro "Host Not Found In Upstream" no Nginx pode ocorrer ao usar contêineres Docker. Esse erro acontece quando o Nginx não consegue resolver ou se conectar ao servidor upstream em sua configuração. Geralmente, é causado por problemas de rede ou configurações incorretas no ambiente Docker.

Resolvendo o Erro "Host Not Found In Upstream" do Nginx

Usando depends_on no docker-compose.yml

A diretiva depends_on no docker-compose.yml ajuda a gerenciar a ordem de inicialização dos contêineres. Ela informa ao Docker para iniciar certos contêineres antes de outros. Isso pode ajudar a evitar o erro "Host Not Found In Upstream" garantindo que os serviços necessários estejam em execução antes do Nginx iniciar.

Para implementar o depends_on em seu arquivo docker-compose.yml, adicione-o sob o serviço Nginx e liste os serviços que ele deve esperar:

version: '3'
services:
  nginx:
    image: nginx
    depends_on:
      - php
    # Outras configurações do Nginx...

  php:
    image: php:fpm
    # Configurações do PHP...

Dica: Verificar a Prontidão do Serviço

Lembre-se que o depends_on apenas espera que o contêiner inicie, não que o serviço dentro dele esteja totalmente pronto. Para configurações mais complexas, considere usar healthchecks ou scripts wait-for-it para garantir que os serviços estejam totalmente operacionais antes do Nginx iniciar.

Atualizando a configuração do Nginx

Verifique a diretiva fastcgi_pass na sua configuração do Nginx. Certifique-se de que ela use o nome correto do serviço conforme definido no seu arquivo docker-compose.yml. Se o seu serviço PHP é chamado "php" no docker-compose.yml, seu fastcgi_pass deve ser assim:

fastcgi_pass php:9000;

Além disso, verifique se os nomes dos serviços na sua configuração do Nginx correspondem aos do seu arquivo docker-compose.yml. Nomes incompatíveis podem causar o erro "Host Not Found In Upstream".

Implementando scripts wait-for-it

Scripts wait-for-it são scripts shell que pausam a inicialização de um contêiner até que um serviço específico esteja pronto. Esses scripts podem ajudar a evitar o erro "Host Not Found In Upstream" garantindo que o Nginx só inicie após os serviços necessários estarem totalmente operacionais.

Para usar um script wait-for-it na sua configuração Docker:

  1. Adicione o script ao diretório do seu projeto.
  2. Atualize seu Dockerfile para incluir o script.
  3. Altere o comando no seu docker-compose.yml para usar o script wait-for-it:
nginx:
  image: nginx
  depends_on:
    - php
  command: ["./wait-for-it.sh", "php:9000", "--", "nginx", "-g", "daemon off;"]
  # Outras configurações do Nginx...

Essa abordagem adiciona proteção contra problemas de temporização que podem causar o erro "Host Not Found In Upstream".

Exemplo: Script de Espera Personalizado

Você pode criar um script de espera personalizado adaptado às suas necessidades específicas. Aqui está um exemplo simples em bash:

#!/bin/bash
set -e

host="$1"
shift
cmd="$@"

until nc -z "$host" 9000; do
  >&2 echo "PHP-FPM não está disponível - aguardando"
  sleep 1
done

>&2 echo "PHP-FPM está pronto - executando comando"
exec $cmd

Salve isso como wait-for-php.sh no diretório do seu projeto, torne-o executável e atualize seu docker-compose.yml para usá-lo:

nginx:
  image: nginx
  depends_on:
    - php
  command: ["./wait-for-php.sh", "php", "nginx", "-g", "daemon off;"]
  # Outras configurações do Nginx...

Soluções Alternativas para Corrigir o Erro do Nginx

Usando redes Docker

Criar redes Docker personalizadas pode ajudar a corrigir o erro "Host Not Found In Upstream". Redes personalizadas permitem que os contêineres se comuniquem usando seus nomes de serviço como hostnames.

Para criar uma rede personalizada:

  1. Defina a rede no seu arquivo docker-compose.yml:
networks:
  myapp_network:
    driver: bridge
  1. Conecte seus serviços a esta rede:
services:
  nginx:
    image: nginx
    networks:
      - myapp_network

  php:
    image: php:fpm
    networks:
      - myapp_network

Ao usar uma rede personalizada, você melhora a comunicação entre contêineres e reduz problemas de resolução de hostnames.

Dica: Isolamento de Rede

Crie redes separadas para diferentes partes da sua aplicação para melhorar a segurança e gerenciar o fluxo de tráfego. Por exemplo, você pode ter uma rede frontend para servidores web e uma rede backend para bancos de dados:

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge

services:
  nginx:
    networks:
      - frontend
  php:
    networks:
      - frontend
      - backend
  database:
    networks:
      - backend

Implementando healthchecks

Healthchecks no docker-compose.yml podem prevenir o erro "Host Not Found In Upstream" garantindo que um serviço esteja pronto antes que outros serviços que dependem dele iniciem.

Para adicionar healthchecks:

  1. Inclua um healthcheck no seu docker-compose.yml para o serviço PHP:
services:
  php:
    image: php:fpm
    healthcheck:
      test: ["CMD", "php-fpm", "-t"]
      interval: 10s
      timeout: 5s
      retries: 3
  1. Atualize o serviço Nginx para depender da saúde do serviço PHP:
services:
  nginx:
    image: nginx
    depends_on:
      php:
        condition: service_healthy

Essa configuração garante que o Nginx só inicie após o serviço PHP estar pronto para aceitar conexões, reduzindo a chance do erro "Host Not Found In Upstream".