【问题标题】:Docker Networking - nginx: [emerg] host not found in upstreamDocker 网络 - nginx:在上游找不到 [emerg] 主机
【发布时间】:2016-02-11 20:53:32
【问题描述】:

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

到目前为止,通过 docker-compose 连接到位于一组不同服务器中的我的 php5-fpm fastcgi 服务器的 nginx 没有问题。最近,当我运行 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 容器正在运行(nginx 退出)时再次运行 docker-compose 命令,则 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 调用?

【问题讨论】:

  • 我也遇到了这个问题。我不确定这是撰写文件的错误,还是 docker 网络本身的错误。

标签: nginx docker docker-compose docker-networking


【解决方案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

【讨论】:

  • 我知道链接,但是 Docker 在一周前发布的 1.9 版本中将它们标记为已弃用,以支持使用 Docker 的网络。我想要一个使用它的解决方案,部分原因是链接存在网络不应该存在的循环链接问题。
  • CHANGELOG.md 中,我没有看到 link 被弃用。我错过了什么吗?
  • 我也没在里面看到;但是,当我使用在我的docker-compose.yml 中定义的链接运行docker-compose --x-networking up 时,我得到了这个明确的警告: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.
  • 好的,我 found 弃用的地方。我唯一的想法是:你是 docker-compose.yml 文件夹中名为 waapi 的文件吗?
  • 是的,它在一个名为waapi的文件夹中
【解决方案2】:

通过链接可以强制执行容器启动顺序。如果没有链接,容器可以按任何顺序启动(或者实际上是一次启动)。

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

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

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

【讨论】:

  • 我该如何进行投票?
【解决方案3】:

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

见:

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

【讨论】:

    【解决方案4】:

    你可以设置 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 {
       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 的责任,而是容器应该自己进行健康检查。

    更新容器

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

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

    【讨论】:

    • 这行不通。阅读 nginx 文档中本节末尾的警告:“如果组中只有一个服务器,则忽略 max_fails、fail_timeout 和 slow_start 参数,并且永远不会认为这样的服务器不可用。”
    • @Ferguzz 这是一个不错的选择。作为一种解决方法,您可以添加同一个容器的两个别名条目,以从同一个容器中创建一个组。
    • 作为替代解决方案,我在同一个问题中提供了使用“volumes_from”链接容器并让它们等到加载其他容器。这对我有用。
    【解决方案5】:

    在引入 depends_on 功能(如下所述)之前,可以使用“volumes_from”作为解决方法。您所要做的就是更改您的 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 的解决方法。

    取决于功能 这可能是一个未来主义的答案。因为该功能尚未在 Docker 中实现(截至 1.9)

    在 Docker 引入的新网络功能中,有一个提议要引入“depends_on”。但是关于相同@https://github.com/docker/compose/issues/374 存在长期争论。因此,一旦实现,功能depends_on 可用于命令容器启动,但目前,您将不得不求助于以下之一:

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

    【讨论】:

    • 这并没有为我解决。
    • @Gijs 如果您可以发布您的确切情况和无效的情况,有人可以在论坛上提供帮助。
    • volumes_from 已弃用
    • 我在 Azure App Service Docker Compose(预览版)中遇到了一个问题。还必须确保我在 nginx 中包含的任何 links: 都使用与服务本身相同的名称,例如 - my-service:my-service 或在本例中为 - mongo:mongo
    【解决方案6】:

    也许避免链接容器问题的最佳选择是 docker 网络 功能

    但是为了完成这项工作,docker 在 /etc/hosts 中为每个容器创建条目,从分配的名称到每个容器。

    使用 docker-compose --x-networking -up 类似于 [docker_compose_folder]-[服务]-[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
    

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

    【讨论】:

      【解决方案7】:

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

      【讨论】:

      • 还要检查容器是否正确配置在同一个网络上(来源:kaos777s8 from link
      【解决方案8】:

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

      resolver 127.0.0.11
      

      在你的 nginx 配置文件中?

      【讨论】:

      • 添加多个解析器,如resolver 127.0.0.11 8.8.8.8;
      • 否,因为它将按照文档中所述循环查询:名称服务器以循环方式查询。
      【解决方案9】:

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

      links:
        - php:waapi_php_1
      

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

      【讨论】:

        【解决方案10】:

        如果您迷路了,请阅读最后一条评论。我已经找到了另一个解决方案。

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

        在这种情况下,如果在您的docker-compose.yml 中,php 的服务称为“api”或类似名称,您必须确保在文件nginx.conf 中以fastcgi_pass 开头的行具有相同的名称作为 php 服务。即fastcgi_pass api:9000;

        【讨论】:

          【解决方案11】:

          我遇到了同样的问题,因为在我的 docker-compose.yml 中定义了两个网络:一个后端和一个前端。
          当我将其更改为在同一默认网络上运行容器时,一切都开始正常工作。

          【讨论】:

          • 这远不是一个答案。
          • 谢谢,这正是我的问题!
          【解决方案12】:

          我的解决方法(经过多次试验和错误):

          • 为了解决这个问题,我必须获取“上游”Docker 容器的全名,通过运行 docker network inspect my-special-docker-network 并获取上游的完整 name 属性找到这样的容器:

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

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

          与以前的工作相反,但现在坏了:

              location / {
                  proxy_pass http://my_upstream_container_name_1:3000
          

          最可能的原因是最近对 Docker Compose 的更改,在容器的默认命名方案中,如 here 所列。

          这似乎发生在我和我的团队工作中,最新版本的 Docker nginx 图像:

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

          【讨论】:

            【解决方案13】:

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

            用于配置

            upstream serv {
                server ex2_app_1:3000;
            }
            

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

            ex2/app/...

            【讨论】:

              【解决方案14】:

              有两点值得一提:

              • 使用同一个网桥
              • 使用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
              

              如果你不指定一个特殊的网桥,它们都将使用相同的默认网桥。

              【讨论】:

                【解决方案15】:

                乍一看,我错过了,我的“web”服务实际上并没有启动,所以这就是为什么 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 中,它应该运行应用程序但它没有发生
                【解决方案16】:

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

                【讨论】:

                  【解决方案17】:

                  我的问题是我忘记在 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
                  

                  【讨论】:

                    【解决方案18】:

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

                    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/

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2017-07-31
                      • 2020-12-22
                      • 1970-01-01
                      • 2020-07-08
                      • 2018-03-03
                      • 1970-01-01
                      • 2020-11-09
                      • 2020-11-08
                      相关资源
                      最近更新 更多