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

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

До сих пор со ссылками не возникало проблем с подключением nginx к моему серверу fastcgi php5-fpm, расположенным на другом сервере в одной группе через 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 работать только с одним вызовом, связанным с док-станцией?

Ответ 1

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

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

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

  • запустите nginx, пока сервер php не встанет - я бы предпочел этот
  • используйте обходной путь volums_from, как описано выше - я бы не стал использовать это из-за утечки объема в ненужные контейнеры.

Ответ 2

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

Ответ 3

Вы можете установить директивы 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 {
   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/compose/blob/master/docs/networking.md), очевидно, что логика повторения для проверки работоспособности других контейнеров не Ответственность за докер и, скорее, контейнеры должны сделать проверку здоровья самостоятельно.

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

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

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

Ответ 4

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

resolver 127.0.0.11

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

Ответ 5

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

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

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

Ответ 6

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

Ответ 7

Имел ту же проблему и решил ее. Пожалуйста, добавьте следующую строку в раздел docker-compose.yml nginx:

links:
  - php:waapi_php_1

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

Ответ 8

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

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

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

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

Ответ 9

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

См:

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

Ответ 10

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

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

с docker-compose - x-networking-up - это что-то вроде [Docker_compose_folder] - [Сервис] - [incremental_number]

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

container_name

в файле 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

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

Ответ 11

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

  • Чтобы обойти эту проблему, мне нужно было получить полное имя Docker-контейнера "upstream", найденное в результате запуска docker network inspect my-special-docker-network и получения свойства full 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 здесь

Ответ 12

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

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

upstream serv {
    server ex2_app_1:3000;
}

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

ех2/приложение/...

Ответ 13

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

  • Используя тот же сетевой мост
  • Использование links для добавления хостов resol

Мой пример:

version: '3'
services:
  mysql:
    image: mysql:5.7
    restart: always
    container_name: mysql
    volumes:
      - ./mysql-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: [email protected]
    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

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

Ответ 14

Добавьте раздел 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

Ответ 15

Вот как я это понимаю, лучший способ, о котором я могу думать.

ADD root /

RUN cp /etc/hosts /etc/hosts.tmp && \
    echo -e "\
127.0.0.1 code_gogs_1 \n\
127.0.0.1 pm_zentao_1 \n\
127.0.0.1 ci_drone_1 \n\
    " >> /etc/hosts && \
    nginx -t && \
# mv: can't rename '/etc/hosts.tmp': Resource busy
# mv /etc/hosts.tmp /etc/hosts
    cat /etc/hosts.tmp > /etc/hosts && \
    rm /etc/hosts.tmp