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

我最近开始迁移到 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 容器运行(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

这是我对 nginx 的 default.conf:

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 调用来工作?

209100 次浏览

链接部分添加到 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

对于链接,有一个强制执行的容器启动顺序。如果没有链接,容器可以以任何顺序启动(或者一次性启动)。

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

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

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

必须使用 docker-gen 之类的工具在后端启动时动态更新 nginx 配置。

参见:

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

您可以设置 nginx 的 max _ ail 和 fault _ timeout 指令,以指示 nginx 应该在上游服务器不可用时失败之前重试到容器的连接请求的 x 个数目。

您可以根据您的基础设施和整个设置启动的速度来调优这两个数字。你可在以下网址查阅有关健康检查部分的详情: Http://nginx.org/en/docs/http/load_balancing.html

以下节选自《 http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server 》(http://nginx.org/en/docs/http/ngx _ http://nginx.html # server) max_fails=number

控件通信失败的次数 服务器,该服务器应该在 ail _ timeout 设置的持续时间内发生 还设置了一个参数,以考虑服务器在一段时间内不可用 默认情况下,不成功的次数 尝试被设置为1。零值禁用 被视为失败的尝试由 快速查询,快速查询,快速查询,快速查询,快速查询,快速查询,快速查询,快速查询,快速查询,快速查询,快速查询, Scgi _ next _ 逆流指令和 memcached _ next _ 逆流指令。

fail_timeout=time

设置指定的失败次数的时间 尝试与服务器通信时,应该考虑 服务器不可用; 以及服务器将处于 默认情况下,参数设置为10 几秒钟。

准确地说,你修改过的 nginx 配置文件应该如下所示(这个脚本假设所有的容器至少提前25秒,如果没有,请在下面的上游部分中修改 fault _ timeout 或 max _ ail) : 注意: 我没有亲自测试这个脚本,所以您可以尝试一下!

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-撰写 为了更新它,旧的容器将被移除,而新的 将以不同的 IP 地址但同一名称加入网络。 运行容器将能够查找该名称并连接到 新地址,但旧地址将停止工作。

如果任何容器与旧容器有连接,则它们 将被关闭。检测这种情况是集装箱的责任 条件,再次查找名称并重新连接。

在引入 Deply _ on 特性(下面讨论)之前,有可能使用“ voluloffrom”作为解决方案。你所要做的就是修改你的文件如下:

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 中实现(从1.9开始)

有人提议在 Docker 引入的新网络特性中引入“视而不见”。但是关于同一个@https://github.com/docker/compose/issues/374有一个长期的争论,因此,一旦它被实现,这个特性  可以被用來命令容器的启动,但是目前,你必須求助于以下其中之一:

  1. 让 nginx 重试,直到 php 服务器启动-我更喜欢这一个
  2. 使用 volums _ from 工作区,如上所述-我会避免使用这个,因为容量泄漏到不必要的容器中。

也许避免链接容器问题的最佳选择是 码头网络特性

但是为了实现这一点,docker 在 /etc/hosts中为每个容器从分配到每个容器的名称中创建条目。

用 Docker-Comose —— x-network-up 就像是 [ docker _ compose _ file ]-[ service ]-[ growth _ number ]

若要不依赖于这些名称的意外更改,应使用该参数

Container _ name

在你的码头-作曲。 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

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

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

文件中找到更多的细节。

还有一篇非常有趣的文章专门讨论这个主题: 控制组合中的启动顺序

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

resolver 127.0.0.11

在你的 nginx 配置文件?

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

links:
- php:waapi_php_1

Nginx config fastcgi _ pass 节中的主机应该链接到 docker-compose. yml nginx 配置中。

如果你如此迷茫,请阅读最后的评论。我已经达成了另一个解决方案。

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

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

假设 php 服务的名称是 php_service,那么代码将是:
在文件 docker-compose.yml

php_service:
build:
dockerfile: ./docker/php/Dockerfile

在文件 nginx.conf

location ~ \.php$ {
fastcgi_pass php_service:9000;
fastcgi_param SCRIPT_FILENAME$document_root$fastcgi_script_name;
include fastcgi_params;
}

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

我的解决办法(经过反复试验后) :

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

    "Containers": {
    "39ad8199184f34585b556d7480dd47de965bc7b38ac03fc0746992f39afac338": {
    "Name": "my_upstream_container_name_1_2478f2b3aca0",
    
  • Then used this in the NGINX my-network.local.conf file in the location block of the proxy_pass property: (Note the addition of the GUID to the container name):

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

As opposed to the previously working, but now broken:

    location / {
proxy_pass http://my_upstream_container_name_1:3000

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

通过 Docker nginx的最新版本,我和我的团队的工作似乎正在发生这种情况:

  • 我已经在 GitHub 给你上与他们打开了一些问题

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

配置

upstream serv {
server ex2_app_1:3000;
}

确保 app 文件夹在 ex2文件夹中:

Ex2/app/...

有两件事值得一提:

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

如果您没有指定一个特殊的网桥,所有这些网桥都将使用相同的默认网桥。

乍一看,我没有注意到,我的“ 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

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

我的问题是我忘记在 Docker-compose. yml in < strong > 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

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

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/

在我的案例中,它也是 nginx: [emerg] host not found in upstream,所以我设法通过在 docker-compose.yml文件中向 nginx 服务添加 depends_on指令来解决它。