125

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

到目前为止,通过 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 容器正在运行(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 调用?

4

18 回答 18

40

这可以通过上述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

在文档中查找更多详细信息。

还有一篇非常有趣的文章专门讨论这个主题:Controlling startup order in Compose

于 2016-08-19T13:05:35.943 回答
27

有可能使用“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)

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

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

您可以设置 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 up 来更新它,旧容器将被删除,新容器将以不同的 IP 地址但同名加入网络。正在运行的容器将能够查找该名称并连接到新地址,但旧地址将停止工作。

如果任何容器与旧容器打开了连接,它们将被关闭。检测这种情况、再次查找名称并重新连接是容器的责任。

于 2015-11-27T09:41:50.253 回答
11

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

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

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

于 2018-02-14T04:21:25.963 回答
7

我的问题是我忘记在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
于 2020-10-05T23:09:52.177 回答
7

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

resolver 127.0.0.11

在你的 nginx 配置文件中?

于 2017-03-30T20:30:47.440 回答
4

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

于 2018-03-02T20:31:50.230 回答
2

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

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/

于 2021-06-05T11:47:31.990 回答
2

乍一看,我错过了,我的“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
于 2019-12-19T09:05:45.920 回答
2

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

links:
  - php:waapi_php_1

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

于 2018-02-10T15:04:06.530 回答
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

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

于 2019-04-18T08:06:46.653 回答
0

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

于 2020-03-28T07:19:19.650 回答
0

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

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

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

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

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

    location / {
        proxy_pass http://my_upstream_container_name_1:3000

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

对于我和我的团队来说,这似乎正在发生,使用最新版本的 Dockernginx映像:

  • 我已经在 docker/compose GitHub 上打开了他们的问题
于 2018-11-26T12:19:10.463 回答
0

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

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

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

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

于 2015-11-11T20:59:41.100 回答
0

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

看:

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

于 2015-11-18T09:00:29.393 回答
0

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

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

使用 docker-compose --x-networking -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

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

于 2015-11-30T14:10:54.537 回答
-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
于 2015-11-10T20:54:19.610 回答
-1

(新到 nginx)在我的情况下,这是错误的文件夹名称

对于配置

upstream serv {
    server ex2_app_1:3000;
}

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

ex2/应用程序/...

于 2019-04-14T18:42:20.920 回答