Docker-分别缩放Nginx和php-fpm


11

我一直在玩docker和docker-compose,有一个问题。

目前我的docker-compose.yml看起来像这样:

app:
    image: myname/php-app
    volumes:
        - /var/www
    environment:
        <SYMFONY_ENVIRONMENT>: dev

web:
    image: myname/nginx
    ports:
        - 80
    links:
        - app
    volumes_from:
        - app

应用程序包含端口9000上的php-fpm和我的应用程序代码。Web是nginx,具有一些配置。

这可以实现我期望的功能,但是为了将nginx连接到php-fpm,我有这条线:

fastcgi_pass    app:9000;

我如何有效地扩展呢?例如,如果我想运行一个nginx容器,但运行三个app容器,那么我肯定要有三个php-fpm实例,所有实例都试图在端口9000上侦听。

如何在每个给定时间将每个php-fpm实例放在不同的端口上,但仍然知道它们在我的nginx配置中的位置?

我采用错误的方法吗?

谢谢!

Answers:


5

一种解决方案是将其他php-fpm实例添加到您的docker-compose文件中,然后使用其他答案中提到的nginx上游来平衡它们之间的负载。这是在此示例docker-compose存储库中完成的:https : //github.com/iamyojimbo/docker-nginx-php-fpm/blob/master/nginx/nginx.conf#L137

upstream php {
    #If there's no directive here, then use round_robin.
    #least_conn;
    server dockernginxphpfpm_php1_1:9000;
    server dockernginxphpfpm_php2_1:9000;
    server dockernginxphpfpm_php3_1:9000;
}

这并不是真正理想的选择,因为当您要放大或缩小时,将需要更改nginx配置和docker-compose.yml。

请注意,9000端口位于容器内部,而不是实际主机,因此端口9000上有多个php-fpm容器无关紧要。

Docker于今年秋天收购了Tutum。他们有一个将HAProxy容器与其api结合使用的解决方案,可以自动将负载均衡器配置调整为正在对其进行负载均衡的运行中的容器。那是一个很好的解决方案。然后,nginx指向分配给负载均衡器的主机名。在收购Tutum之后,也许Docker将进一步将这种解决方案集成到他们的工具中。这里有一篇关于它的文章:https : //web.archive.org/web/20160628133445/https : //support.tutum.co/support/solutions/articles/5000050235-load-balancing-a-web-service

Tutum目前是一项付费服务​​。Rancher是一个开源项目,提供了类似的负载平衡功能。他们还具有“ rancher-compose.yml”,可以定义docker-compose.yml中服务设置的负载平衡和缩放。 http://rancher.com/the-magical-moment-when-container-load-balancing-meets-service-discovery/ http://docs.rancher.com/rancher/concepts/#load-balancer

更新2017/03/06:我使用了一个名为interlock的项目,该项目可与Docker一起使用,以自动更新nginx配置并重新启动它。另请参阅@iwaseatenbyagrue的答案,其中包含其他方法。



0

如果您的Nginx和php-fpm容器位于同一主机上,则可以在主机上配置一个供nginx容器使用的小型dnsmasq实例,并运行一个脚本,以在容器的IP地址包含以下内容时自动更新DNS记录改变了。

我编写了一个小脚本来执行此操作(粘贴在下面),该脚本会自动更新与容器名称相同的DNS记录,并将它们指向容器的IP地址:

#!/bin/bash

# 10 seconds interval time by default
INTERVAL=${INTERVAL:-10}

# dnsmasq config directory
DNSMASQ_CONFIG=${DNSMASQ_CONFIG:-.}

# commands used in this script
DOCKER=${DOCKER:-docker}
SLEEP=${SLEEP:-sleep}
TAIL=${TAIL:-tail}

declare -A service_map

while true
do
    changed=false
    while read line
    do
        name=${line##* }
        ip=$(${DOCKER} inspect --format '{{.NetworkSettings.IPAddress}}' $name)
        if [ -z ${service_map[$name]} ] || [ ${service_map[$name]} != $ip ] # IP addr changed
        then
            service_map[$name]=$ip
            # write to file
            echo $name has a new IP Address $ip >&2
            echo "host-record=$name,$ip"  > "${DNSMASQ_CONFIG}/docker-$name"
            changed=true
        fi
    done < <(${DOCKER} ps | ${TAIL} -n +2)

    # a change of IP address occured, restart dnsmasq
    if [ $changed = true ]
    then
        systemctl restart dnsmasq
    fi

    ${SLEEP} $INTERVAL
done

然后,使用来启动您的nginx容器--dns host-ip-address,其中host-ip-address是接口上主机的IP地址docker0

您的Nginx配置应动态解析名称:

server {
  resolver host-ip-address;
  listen 80;
  server_name @server_name@;
  root /var/www/@root@;
  index index.html index.htm index.php;

  location ~ ^(.+?\.php)(/.*)?$ {
    try_files $uri =404;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$1;
    set $backend "@fastcgi_server@";
    fastcgi_pass $backend;
  }
}

参考文献:

如果您的nginx和php-fpm位于不同的主机上,则可以尝试@smaj的答案。


0

另一种方法可能是研究像领事模板

当然,在某些时候,可能需要提及Kubernetes

但是,您可以通过查看消耗性的docker事件可以为您做些什么(运行docker events --since 0一个快速示例),考虑使用稍微多一点的“字符串和胶带”方法。

让脚本查看这些事件(考虑到有多个客户端软件包,包括用于python,go等的客户端软件包),修改配置文件并重新加载nginx(即使用consul-template方法,但无需领事)。

但是,要回到原来的前提:只要您的php-fpm容器是使用自己的网络启动的(即不共享另一个容器(例如nginx容器)的网络),那么您可以在端口上侦听尽可能多的容器所需的9000-由于它们具有每个容器的IP,因此端口“冲突”没有问题。

您如何扩展它可能取决于您的最终目标/用例,但是您可能要考虑的一件事是在nginx和php-fpm节点之间放置HAproxy。这可能允许您做的一件事就是简单地docker network为您的php-fpm服务器指定一个范围(并可能创建一个)(即172.18.0.0/24),并将HAproxy配置为尝试使用该范围内的任何IP作为后端。由于HAproxy具有运行状况检查,因此它可以快速确定哪些地址存在,并可以使用它们。

请参阅/programming/1358198/nginx-removing-upstream-servers-from-pool,以获取有关nginx vs haproxy如何处理上游的讨论。

除非为此使用了专用的docker网络,否则您可能需要对php-fpm节点进行一些手动IP管理。


0

尽管这篇文章来自2015年,我觉得我很生气(对不起社区),但是我觉得在这一点上添加很有价值:

如今(由于提到了Kubernetes),当您使用Docker时,可以非常轻松地使用Kubernetes或Docker Swarm解决此问题。两个协调器都将接收您的Docker节点(一个节点=一台服务器,上面装有Docker),您可以为其部署服务,它们将使用覆盖网络为您管理端口挑战。

正如我更精通Docker Swarm一样,这是解决该问题的方法(假设您有一个Docker节点):

初始化群:

docker swarm init

进入您的项目根目录

cd some/project/root

从docker-compose.yml创建一个堆栈堆栈(而不是使用docker-compose):

docker stack deploy -c docker-compose.yml myApp

这将创建一个名为“ myApp”的码头工人服务堆栈,并将为您管理端口。这意味着:您只需要在docker-compose文件的php-fpm服务中添加一个“ port:9000:9000”定义,然后您就可以扩展php-fpm服务(例如3个实例),而swarm将自动魔术地平衡三个实例之间的请求,而无需任何进一步的工作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.