我最近开始迁移到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
这是我对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调用?
有可能使用“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 feature这可能是一个未来主义的答案。因为Docker中尚未实现该功能(截至1.9)
有人建议在Docker引入的新网络功能中引入“depends_on”。但是关于相同的@ https://github.com/docker/compose/issues/374存在长期争论。因此,一旦实现,功能depends_on可用于订购容器启动,但此刻,您将不得不求助于以下之一:
也许避免链接容器问题的最佳选择是docker网络功能
但为了使这项工作,docker在/ etc / hosts中为每个容器创建条目,从指定的名称到每个容器。
与docker-compose --x-networking -up类似[docker_compose_folder] - [service] - [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
确保它与您的配置文件中为此服务指定的名称相同。我很确定有更好的方法可以做到这一点,但这是一个很好的方法。
我的解决方法(经过多次试验和错误):
docker network inspect my-special-docker-network
并获取上游容器的完整name
属性来找到:
"Containers": {
"39ad8199184f34585b556d7480dd47de965bc7b38ac03fc0746992f39afac338": {
"Name": "my_upstream_container_name_1_2478f2b3aca0",
my-network.local.conf
属性的location
块中的NGINX 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的更改,在其默认的容器命名方案中,如here所列。
这似乎发生在我和我的团队工作中,最新版本的Docker nginx
图像:
(nginx新手)在我的情况下,这是错误的文件夹名称
对于配置
upstream serv {
server ex2_app_1:3000;
}
确保app文件夹位于ex2文件夹中:
EX2 /应用/ ...
值得一提的两件事:
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: 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
如果未指定特殊网桥,则所有网桥都将使用相同的默认网桥。
将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
这就是我如何理解它,这是我能想到的最佳方式。
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
这可以通过提到的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
您可以设置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地址但名称相同的方式加入网络。运行容器将能够查找该名称并连接到新地址,但旧地址将停止工作。
如果任何容器的连接打开旧容器,它们将被关闭。容器有责任检测此情况,再次查找名称并重新连接。
我相信Nginx不会考虑Docker解析器(127.0.0.11),所以请你尝试添加:
resolver 127.0.0.11
在你的nginx配置文件中?
如果你因为阅读上一条评论而迷路了。我已达成另一种解决方案。
主要问题是您命名服务名称的方式。
在这种情况下,如果在你的docker-compose.yml
中,php的服务被称为“api”或类似的东西,你必须确保在文件nginx.conf
中以fastcgi_pass
开头的行与php服务具有相同的名称。即fastcgi_pass api:9000;
有一个问题,直到docker-compose.yml中定义了两个网络:后端和前端。在同一默认网络上运行所有容器时一切正常。
有同样的问题并解决了它。请将以下行添加到docker-compose.yml nginx部分:
links:
- php:waapi_php_1
nginx config fastcgi_pass部分中的主机应该在docker-compose.yml nginx配置中链接。
使用链接有一个强制执行容器启动的顺序。没有链接,容器可以以任何顺序启动(或者实际上一次启动)。
我认为旧的设置可能会遇到同样的问题,如果waapi_php_1
容器启动缓慢。
我认为要让它工作,你可以创建一个nginx入口点脚本,轮询并等待php容器启动和准备好。
我不确定nginx是否有任何方法可以自动重试与上游的连接,但如果确实如此,那将是一个更好的选择。
当你的后端启动时,你必须使用像docker-gen这样的东西来动态更新nginx配置。
看到:
我相信Nginx +(高级版)也包含一个解析参数(http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream)