Docker Networking - nginx: хост [Emerg] не найден в восходящем потоке

Недавно я начал переходить на сетевые функции Docker 1.9 и Docker-Compose 1.5, чтобы заменить использование ссылок.

Пока со ссылками не было проблем с подключением nginx к моему серверу php5-fpm fastcgi, расположенному на другом сервере в одной группе, через docker-compose. Однако недавно, когда я запускаю docker-compose --x-networking up, мои контейнеры php-fpm, mongo и nginx загружаются, однако nginx сразу завершает работу с [emerg] 1#1: host not found in upstream "waapi_php_1" in /etc/nginx/conf.d/default.conf:16

Однако, если я снова запускаю команду docker-compose во время работы контейнеров php и mongo (nginx завершен), nginx запускается и с этого момента работает нормально.

Это мой 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

Это мой default.conf для 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;
    }
}

Как заставить nginx работать только с одним вызовом docker-compose?


person Attila Szeremi    schedule 10.11.2015    source источник
comment
Я тоже с этим сталкиваюсь. Я не уверен, ошибка ли это в файле создания или в самой сети докеров.   -  person jrdn    schedule 27.11.2015


Ответы (18)


Существует возможность использовать "volume_from" в качестве обходного пути, пока не будет введена функция depends_on (обсуждается ниже). Все, что вам нужно сделать, это изменить файл docker-compose, как показано ниже:

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

Одно большое предостережение в вышеупомянутом подходе заключается в том, что тома php открываются для nginx, что нежелательно. Но на данный момент это одно решение, специфичное для докеров, которое можно использовать.

Функция зависит_он. Вероятно, это был бы футуристический ответ. Поскольку эта функциональность еще не реализована в Docker (начиная с версии 1.9)

Есть предложение ввести "depends_on" в новую сетевую функцию, представленную Docker. Но по поводу того же @ https://github.com/docker/compose/issues/374 Следовательно, после того, как он будет реализован, функция depends_on может быть использована для заказа запуска контейнера, но на данный момент вам придется прибегнуть к одному из следующих вариантов:

  1. заставить nginx повторять попытку, пока не будет запущен php-сервер - я бы предпочел этот
  2. используйте обходной путь volums_from, как описано выше - я бы не стал его использовать из-за утечки объема в ненужные контейнеры.
person Phani    schedule 28.11.2015
comment
Это не помогло мне. - person Gijs; 18.02.2016
comment
@Gijs, если вы можете опубликовать ваш конкретный случай и что не сработало, кто-нибудь может помочь на форуме. - person Phani; 11.03.2016
comment
volume_from устарели - person Roma Rush; 19.08.2018
comment
Я столкнулся с проблемой в Docker Compose службы приложений Azure (предварительная версия) с этим. Также необходимо было убедиться, что любой links:, который я включил в nginx, использовал то же имя, что и сама служба, например - my-service:my-service или в этом примере - mongo:mongo. - person greg; 21.07.2020

Это можно решить с помощью упомянутой директивы depends_on, поскольку она реализована сейчас (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

Успешно протестирован с:

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

Дополнительные сведения см. В документации.

Также есть очень интересная статья, посвященная этой теме: Управление порядком запуска в Compose

person czerasz    schedule 19.08.2016
comment
также убедитесь, что контейнеры правильно настроены для работы в одной сети (источник: kaos777s8 из ссылка) - person Mark Teese; 12.02.2021

Вы можете установить директивы max_fails и fail_timeout для nginx, чтобы указать, что nginx должен повторить x запросов на соединение с контейнером, прежде чем произойдет сбой при недоступности вышестоящего сервера.

Вы можете настроить эти два числа в соответствии с вашей инфраструктурой и скоростью, с которой происходит установка. Дополнительную информацию о разделе проверки работоспособности можно найти по следующему URL-адресу: http://nginx.org/en/docs/http/load_balancing.html

Ниже приводится выдержка из http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server max_fails=number

устанавливает количество неудачных попыток связи с сервером, которые должны произойти в течение периода, установленного параметром fail_timeout, чтобы считать сервер недоступным в течение периода, также установленного параметром fail_timeout. По умолчанию количество неудачных попыток равно 1. Нулевое значение отключает учет попыток. То, что считается неудачной попыткой, определяется директивами proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream и memcached_next_upstream.

fail_timeout=time

устанавливает время, в течение которого должно произойти указанное количество неудачных попыток связи с сервером, чтобы сервер считался недоступным; и период времени, в течение которого сервер будет считаться недоступным. По умолчанию параметр установлен на 10 секунд.

Чтобы быть точным, ваш измененный файл конфигурации nginx должен быть следующим (этот сценарий предполагает, что все контейнеры работают не менее чем на 25 секунд, в противном случае измените fail_timeout или max_fails в нижнем разделе восходящего потока): Примечание: я не Протестируйте сценарий самостоятельно, чтобы вы могли попробовать!

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

Кроме того, согласно следующему примечанию от docker (https://github.com/docker/docker.github.io/blob/master/compose/networking.md#update-containers), очевидно, что логика повтора для проверки работоспособности другие контейнеры не являются обязанностью докера, и контейнеры должны сами выполнять проверку работоспособности.

Обновление контейнеров

Если вы измените конфигурацию службы и запустите docker-compose up для ее обновления, старый контейнер будет удален, а новый присоединится к сети под другим IP-адресом, но с тем же именем. Запущенные контейнеры смогут найти это имя и подключиться к новому адресу, но старый адрес перестанет работать.

Если какие-либо контейнеры имеют соединения, открытые со старым контейнером, они будут закрыты. Ответственность за обнаружение этого условия, повторный поиск имени и повторное подключение - это контейнер.

person Phani    schedule 27.11.2015
comment
Это не сработает. прочтите предостережение в конце этого раздела в документации nginx: если в группе только один сервер, параметры max_fails, fail_timeout и slow_start игнорируются, и такой сервер никогда не будет считаться недоступным. - person Ferguzz; 07.01.2016
comment
@Ferguzz, это был хороший улов. В качестве обходного пути вы можете добавить две записи псевдонима одного и того же контейнера, чтобы создать группу из одного и того же контейнера. - person Phani; 07.01.2016
comment
В качестве альтернативного решения я предложил в том же вопросе использовать volume_from, чтобы связать контейнеры и заставить их ждать загрузки других контейнеров. Это работает для меня. - person Phani; 07.01.2016

Если вы так растерялись, прочтите последний комментарий. Я нашел другое решение.

Основная проблема заключается в том, как вы назвали имена сервисов.

В этом случае, если в вашем docker-compose.yml служба для php называется "api" или что-то в этом роде, вы должны убедиться, что в файле nginx.conf строка, начинающаяся с fastcgi_pass, имеет то же имя, что и служба php. т.е. fastcgi_pass api:9000;

person julian    schedule 14.02.2018

Я считаю, что Nginx не учитывает преобразователь Docker (127.0.0.11), поэтому, пожалуйста, можете попробовать добавить:

resolver 127.0.0.11

в вашем файле конфигурации nginx?

person Thomas Decaux    schedule 30.03.2017
comment
Добавьте несколько преобразователей, например resolver 127.0.0.11 8.8.8.8; - person Leonardo Chaia; 18.11.2017
comment
Нет, так как он будет запрашивать в циклическом режиме, как указано в документации: серверы имен запрашиваются в циклическом режиме. - person dalore; 03.04.2018

У меня была такая же проблема, потому что в моем docker-compose.yml были определены две сети: одна серверная часть и одна интерфейсная.
Когда я изменил это, чтобы запускать контейнеры в той же сети по умолчанию, все стало работать нормально.

person smola    schedule 02.03.2018
comment
Это далеко не ответ. - person dargmuesli; 07.10.2019
comment
Спасибо, это была моя проблема! - person Anders Bornholm; 13.01.2021

Моя проблема заключалась в том, что я забыл указать сетевой псевдоним в docker-compose.yml в php-fpm

    networks:
      - u-online

Работает хорошо!

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
person Юрий Светлов    schedule 05.10.2020

Была такая же проблема и решил ее. Добавьте следующую строку в раздел docker-compose.yml nginx:

links:
  - php:waapi_php_1

Хост в конфигурации nginx раздел fastcgi_pass должен быть связан внутри конфигурации nginx docker-compose.yml.

person st0at    schedule 10.02.2018

На первый взгляд я упустил, что моя "веб-служба" на самом деле не запускалась, поэтому nginx не мог найти ни одного хоста.

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
person Alveona    schedule 19.12.2019
comment
эй, у меня такая же проблема. Мое приложение не запущено, поэтому я получаю ту же ошибку. Я поместил uwsgi-файл как run.py в app.ini, который должен был запустить приложение, но этого не произошло - person isrj5; 17.02.2020

Стоит упомянуть две вещи:

  • Использование того же сетевого моста
  • Использование links для добавления разрешения хостов

Мой пример:

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

Если вы не укажете специальный сетевой мост, все они будут использовать один и тот же мост по умолчанию.

person NOZUONOHIGH    schedule 18.04.2019

Я нашел решение для сервисов, которые могут быть отключены для локальной разработки. Просто используйте переменные, которые предотвращают аварийное отключение и работают после того, как услуга будет доступна.

server {
    location ^~ /api/ {
        # other config entries omitted for breavity
    
        set $upstream http://api.awesome.com:9000;

        # nginx will now start if host is not reachable
        fastcgi_pass    $upstream; 
        fastcgi_index   index.php;
    }
}

источник: https://sandro-keil.de/blog/let-nginx-start-if-upstream-host-is-unavailable-or-down/

person Dmitry    schedule 05.06.2021

С помощью ссылок выполняется принудительный запуск контейнера. Без ссылок контейнеры могут запускаться в любом порядке (а на самом деле все сразу).

Я думаю, что старая установка могла бы столкнуться с той же проблемой, если бы контейнер waapi_php_1 запускался медленно.

Я думаю, чтобы заставить его работать, вы могли бы создать сценарий точки входа nginx, который опрашивает и ждет, пока контейнер php будет запущен и готов.

Я не уверен, есть ли у nginx способ автоматически повторить попытку подключения к восходящему потоку, но если это так, это был бы лучший вариант.

person dnephin    schedule 11.11.2015
comment
А как мне сделать опрос? - person Attila Szeremi; 12.11.2015

Вы должны использовать что-то вроде docker-gen для динамического обновления конфигурации nginx, когда ваш бэкэнд запущен.

Видеть:

Я считаю, что Nginx + (премиум-версия) также содержит параметр разрешения (http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream)

person Laurent B    schedule 18.11.2015

Возможно, лучший способ избежать проблем с связыванием контейнеров - это функции сети докеров.

Но для этого docker создает записи в / etc / hosts для каждого контейнера из присвоенных им имен для каждого контейнера.

с docker-compose --x-network -up это что-то вроде [docker_compose_folder] - [service] - [incremental_number]

Чтобы не зависеть от неожиданных изменений этих имен, следует использовать параметр

имя_контейнера

в вашем docker-compose.yml следующим образом:

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

Убедитесь, что это то же имя, что и в вашем файле конфигурации для этой службы. Я почти уверен, что есть способы сделать это лучше, но для начала это хороший подход.

person JorelC    schedule 30.11.2015

Мое решение (после долгих проб и ошибок):

  • Чтобы обойти эту проблему, мне нужно было получить полное имя восходящего контейнера Docker, которое можно найти, запустив docker network inspect my-special-docker-network и получив полное свойство name восходящего контейнера как таковое:

    "Containers": {
         "39ad8199184f34585b556d7480dd47de965bc7b38ac03fc0746992f39afac338": {
              "Name": "my_upstream_container_name_1_2478f2b3aca0",
    
  • Затем использовал это в файле NGINX my-network.local.conf в блоке location свойства proxy_pass: (обратите внимание на добавление GUID к имени контейнера):

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

В отличие от ранее работавших, но теперь сломанных:

    location / {
        proxy_pass http://my_upstream_container_name_1:3000

Наиболее вероятная причина - недавнее изменение в Docker Compose схемы именования контейнеров по умолчанию, как указано здесь.

Похоже, это происходит со мной и моей командой на работе с последними версиями образа Docker nginx:

  • Я столкнулся с ними в docker / compose GitHub здесь
person Erin Eland    schedule 26.11.2018

эта ошибка появилась, потому что мое php-fpm изображение включило cron, и я не знаю, почему

person Ruan Nawe    schedule 28.03.2020

Добавьте раздел links в конфигурацию контейнера nginx.

Вы должны сделать контейнер php видимым для контейнера nginx.

nginx:
  image: nginx
  ports:
    - "42080:80"
  volumes:
    - ./config/docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
  links:
    - php:waapi_php_1
person nessuno    schedule 10.11.2015
comment
Я знаю о ссылках, однако Docker пометил их как устаревшие в версии 1.9, которая вышла неделю назад, в пользу использования сети Docker. Мне нужно решение, которое использует это, отчасти потому, что у ссылок есть проблема с циклическими ссылками, которых в сети быть не должно. - person Attila Szeremi; 11.11.2015
comment
В CHANGELOG.md я не вижу, чтобы link устарел. Я что-то упускаю? - person nessuno; 11.11.2015
comment
Я этого там тоже не видел; однако, когда я запускаю docker-compose --x-networking up со ссылками, определенными в моем docker-compose.yml, я получаю четкое предупреждение: 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. - person Attila Szeremi; 11.11.2015
comment
Хорошо, я обнаружил, где объявлено устаревание. Единственная идея, которая у меня есть: вы docker-compose.yml файл в папке с именем waapi? - person nessuno; 11.11.2015
comment
Да, он находится в папке с именем waapi - person Attila Szeremi; 11.11.2015
comment
Хм .. кто знает, имеет ли значение порядок. Попробуйте поставить блок php перед блоком nginx в docker-compose.yml - person nessuno; 11.11.2015

(впервые в nginx) В моем случае имя папки было неправильным

Для конфигурации

upstream serv {
    server ex2_app_1:3000;
}

убедитесь, что папка приложения находится в папке ex2:

ex2 / app / ...

person vijeth.ag    schedule 14.04.2019