Docker Networking - nginx:[emerg]主机在上游找不到

时间:2015-11-10 20:37:58

标签: nginx docker docker-compose docker-networking

我最近开始迁移到Docker 1.9和Docker-Compose 1.5的网络功能,以替换使用链接。

到目前为止链接没有问题,nginx通过docker-compose连接到位于一组不同服务器中的php5-fpm fastcgi服务器。最近,当我运行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

但是,如果我在php和mongo容器运行时再次运行docker-compose命令(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调用?

19 个答案:

答案 0 :(得分:20)

有可能使用" volumes_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的解决方法。

depends_on功能 这可能是一个未来主义的答案。因为Docker中没有实现该功能(从1.9开始)

有人建议引入" depends_on"在Docker引入的新网络功能中。但是关于相同的@ https://github.com/docker/compose/issues/374存在长期争论。因此,一旦实现,功能depends_on可用于订购容器启动,但此刻,您将不得不诉诸其中一个以下内容:

  1. 让nginx重试,直到php服务器启动 - 我更喜欢这个
  2. 使用volums_from如上所述的解决方法 - 我会避免使用它,因为卷泄漏到不必要的容器中。

答案 1 :(得分:15)

这可以通过提到的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

documentation

中查找更多详情

还有一篇非常有趣的文章致力于这个主题:Controlling startup order in Compose

答案 2 :(得分:8)

您可以设置nginx的max_fails和fail_timeout指令,以指示在上游服务器不可用失败之前,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;
    }
}

另外,根据docker(https://github.com/docker/compose/blob/master/docs/networking.md)的以下注释,显然用于检查其他容器的运行状况的重试逻辑不是docker的责任,而是容器应该自己进行运行状况检查。

  

更新容器

     

如果您对服务进行配置更改并运行docker-compose   要更新它,旧容器将被删除和新容器   将以不同的IP地址加入网络,但名称相同。   运行容器将能够查找该名称并连接到   新地址,但旧地址将停止工作。

     

如果任何容器与旧容器的连接打开,则它们   将被关闭。检测到这一点是容器的责任   条件,再次查找名称并重新连接。

答案 3 :(得分:4)

我相信Nginx不会考虑Docker解析器(127.0.0.11),所以请你尝试添加:

resolver 127.0.0.11
在你的nginx配置文件中

答案 4 :(得分:3)

如果你因为阅读上一条评论而迷路了。我已经达成了另一种解决方案。

主要问题是您命名服务名称的方式。

在这种情况下,如果在你的docker-compose.yml中,就会调用php的服务" api"或类似的东西,你必须确保在文件nginx.conf中以fastcgi_pass开头的行与php服务具有相同的名称。即fastcgi_pass api:9000;

答案 5 :(得分:2)

具有相同的问题,直到docker-compose.yml定义了两个网络:后端和前端。在同一默认网络上运行所有容器时一切正常。

答案 6 :(得分:1)

遇到同样的问题并解决了它。请将以下行添加到docker-compose.yml nginx部分:

links:
  - php:waapi_php_1

nginx config fastcgi_pass部分中的主机应该在docker-compose.yml nginx配置中链接。

答案 7 :(得分:0)

我找到了服务的解决方案,该解决方案可能因本地开发而被禁用。只需使用变量即可防止紧急关闭并在服务可用后工作。

server {
    location ^~ /api/ {
        # other config entries omitted for breavity
    
        set $upstream 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/

答案 8 :(得分:0)

我的问题是我忘记在其中指定网络别名 php-fpm

中的docker-compose.yml
    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

答案 9 :(得分:0)

出现此错误是因为我的php-fpm图片启用了cron,我不知道为什么

答案 10 :(得分:0)

乍一看,我错过了我的“网络”服务实际上并未启动的原因,因此这就是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

答案 11 :(得分:0)

两件事值得一提:

  • 使用相同的网桥
  • 使用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

如果您未指定特殊的网桥,则它们都将使用相同的默认网桥。

答案 12 :(得分:0)

(nginx的新手) 就我而言,这是错误的文件夹名称

对于配置

upstream serv {
    server ex2_app_1:3000;
}

确保app文件夹位于ex2文件夹中

ex2 / app /...

答案 13 :(得分:0)

我的解决方法(经过反复尝试):

  • 为了解决这个问题,我必须获取“上游” Docker容器的全名,方法是运行docker network inspect my-special-docker-network并获取完整的{{ 1}}属性,例如:

    name
  • 然后在"Containers": { "39ad8199184f34585b556d7480dd47de965bc7b38ac03fc0746992f39afac338": { "Name": "my_upstream_container_name_1_2478f2b3aca0", 属性的my-network.local.conf块的NGINX location文件中使用了此命令:(请注意,在容器名称中添加了GUID):

    proxy_pass

与以前的工作方式相反,但现在已失效:

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

最可能的原因是最近对Docker Compose进行了更改,其容器默认命名方案为here

使用最新版本的Docker location / { proxy_pass http://my_upstream_container_name_1:3000 映像,这似乎对我和我的团队正在发生:

  • 我已经在docker / compose GitHub here
  • 上打开了有关它们的问题

答案 14 :(得分:0)

避免链接容器问题的最佳选择可能是 docker networking 功能

但是为了使这项工作,docker在 / 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

确保它与您的配置文件中为此服务指定的名称相同。我很确定有更好的方法可以做到这一点,但这是一个很好的方法。

答案 15 :(得分:0)

当你的后端启动时,你必须使用像docker-gen这样的东西来动态更新nginx配置。

请参阅:

我相信Nginx +(高级版)也包含一个解析参数(http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream

答案 16 :(得分:0)

使用链接有一个强制执行容器启动的顺序。没有链接,容器可以以任何顺序启动(或者实际上一次启动)。

如果waapi_php_1容器启动缓慢,我认为旧设置可能遇到同样的问题。

我认为要让它工作,你可以创建一个nginx入口点脚本,轮询并等待php容器启动和准备好。

我不确定nginx是否有办法自动重试与上游的连接,但如果确实如此,那将是一个更好的选择。

答案 17 :(得分:-1)

这就是我如何理解它,这是我能想到的最佳方式。

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

答案 18 :(得分:-1)

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