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

99

Недавно я начал переходить на сетевые функции 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?

Аттила Сереми
источник
3
Я тоже с этим сталкиваюсь. Я не уверен, ошибка ли это в файле создания или в самой сети докеров.
jrdn

Ответы:

26

Существует возможность использовать "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, что нежелательно. Но на данный момент это одно решение, специфичное для докеров, которое можно использовать.

зависимости_on Feature Это, вероятно, будет футуристическим ответом. Поскольку эта функциональность еще не реализована в Docker (начиная с версии 1.9)

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

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

Это можно решить с помощью упомянутой 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

Czerasz
источник
12

Вы можете установить директивы 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;
    }
}

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

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

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

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

Фани
источник
3
Это не сработает. прочтите предостережение в конце этого раздела в документации nginx: «Если в группе есть только один сервер, параметры max_fails, fail_timeout и slow_start игнорируются, и такой сервер никогда не будет считаться недоступным».
Ferguzz 07
1
@Ferguzz, это был хороший улов. В качестве обходного пути вы можете добавить две записи псевдонима одного и того же контейнера, чтобы создать группу из одного контейнера.
Phani 07
В качестве альтернативного решения я предложил в том же вопросе использовать "volume_from", чтобы связать контейнеры и заставить их ждать загрузки других контейнеров. Это работает для меня.
Phani 07
7

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

resolver 127.0.0.11

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

Томас Деко
источник
Добавить несколько арбитров какresolver 127.0.0.11 8.8.8.8;
Leonardo Хая
1
Нет, поскольку он будет запрашивать в циклическом режиме, как указано в документации: серверы имен запрашиваются в циклическом режиме.
dalore
6

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

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

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

юлианский
источник
3

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

смола
источник
Это далеко не ответ.
dargmuesli 07
2

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

links:
  - php:waapi_php_1

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

st0at
источник
1

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

  • Использование того же сетевого моста
  • Использование 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

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

NOZUON ВЫСОКИЙ
источник
1

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

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

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

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

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

днефин
источник
А как мне сделать опрос?
Аттила Шереми,
0

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

Увидеть:

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

Лоран Б
источник
0

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

Но для этого 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

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

JorelC
источник
0

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

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

    "Containers": {
         "39ad8199184f34585b556d7480dd47de965bc7b38ac03fc0746992f39afac338": {
              "Name": "my_upstream_container_name_1_2478f2b3aca0",
    
  • Затем использовал это в my-network.local.confфайле NGINX в 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 в их схеме именования по умолчанию для контейнеров, как указано здесь. .

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

  • Я открыл с ними проблемы в докере / сочиняю GitHub здесь
arcadia_168
источник
0

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

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

upstream serv {
    server ex2_app_1:3000;
}

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

ex2 / app / ...

vijeth.ag
источник
0

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

Руан Наве
источник
0

Моя проблема заключалась в том, что я забыл указать сетевой псевдоним в 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
Юрий Светлов
источник
-1

Добавьте раздел ссылок в конфигурацию контейнера 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
Несуно
источник
1
Я знаю о ссылках, однако Docker пометил их как устаревшие в версии 1.9, которая вышла неделю назад, в пользу использования сети Docker. Мне нужно решение, которое использует это, отчасти потому, что у ссылок есть проблема с циклическими ссылками, которых в сети быть не должно.
Аттила Шереми
1
В CHANGELOG.md я не вижу, linkчто он устарел. Я что-то упускаю?
nessuno
Я этого там тоже не видел; однако, когда я запускаю 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.
Аттила Шереми
Хорошо, я нашел, где устарело. Единственная идея, которая у меня есть: вы docker-compose.ymlхраните файл в папке с именем waapi?
nessuno
Да, он находится в папке под названиемwaapi
Attila Szeremi